output_structure_legacy.cpp
Go to the documentation of this file.
1 
29 #include "../../include/output/COutputLegacy.hpp"
30 
31 #include "../../../Common/include/geometry_structure.hpp"
32 #include "../../include/solver_structure.hpp"
33 
35 
38 
39  unsigned short iDim, iZone, iSpan, iMarker;
40 
41  /*--- Initialize point and connectivity counters to zero. ---*/
42 
43  nGlobal_Poin = 0;
44  nSurf_Poin = 0;
45  nGlobal_Elem = 0;
46  nSurf_Elem = 0;
47  nGlobal_Tria = 0;
48  nGlobal_Quad = 0;
49  nGlobal_Tetr = 0;
50  nGlobal_Hexa = 0;
51  nGlobal_Pris = 0;
52  nGlobal_Pyra = 0;
53  nGlobal_Line = 0;
54  nGlobal_BoundTria = 0;
55  nGlobal_BoundQuad = 0;
56 
57  /*--- Initialize pointers to NULL ---*/
58 
59  Coords = NULL;
60  Conn_Line = NULL; Conn_BoundTria = NULL; Conn_BoundQuad = NULL;
61  Conn_Tria = NULL; Conn_Quad = NULL; Conn_Tetr = NULL;
62  Conn_Hexa = NULL; Conn_Pris = NULL; Conn_Pyra = NULL;
63  Data = NULL;
64 
65  /*--- Initialize parallel pointers to NULL ---*/
66 
67  nGlobal_Poin_Par = 0;
68  nGlobal_Elem_Par = 0;
69  nGlobal_Surf_Poin = 0;
70  nParallel_Poin = 0;
71  nSurf_Poin_Par = 0;
72  nSurf_Elem_Par = 0;
73  nParallel_Tria = 0;
74  nParallel_Quad = 0;
75  nParallel_Tetr = 0;
76  nParallel_Hexa = 0;
77  nParallel_Pris = 0;
78  nParallel_Pyra = 0;
79  nParallel_Line = 0;
80  nParallel_BoundTria = 0;
81  nParallel_BoundQuad = 0;
82 
83  /*--- Initialize pointers to NULL ---*/
84 
85  Conn_BoundLine_Par = NULL; Conn_BoundTria_Par = NULL; Conn_BoundQuad_Par = NULL;
86  Conn_Tria_Par = NULL; Conn_Quad_Par = NULL; Conn_Tetr_Par = NULL;
87  Conn_Hexa_Par = NULL; Conn_Pris_Par = NULL; Conn_Pyra_Par = NULL;
88 
89  Local_Data = NULL;
90  Local_Data_Copy = NULL;
91  Parallel_Data = NULL;
92  Parallel_Surf_Data = NULL;
93 
94  /*--- Initialize structures for storing linear partitioning offsets ---*/
95 
96  nGlobalPoint_Sort = 0;
97  nLocalPoint_Sort = 0;
98  nPoint_Restart = 0;
99 
100  Local_Halo_Sort = NULL;
101 
102  beg_node = NULL;
103  end_node = NULL;
104 
105  nPointLinear = NULL;
106  nPointCumulative = NULL;
107 
108  /*--- Initialize CGNS write flag ---*/
109 
110  wrote_base_file = false;
111 
112  /*--- Initialize CGNS write flag ---*/
113 
114  wrote_CGNS_base = false;
115 
116  /*--- Initialize Tecplot surface flag ---*/
117 
118  wrote_surf_file = false;
119 
120  /*--- Initialize Paraview write flag ---*/
121 
122  wrote_Paraview_base = false;
123 
124  /*--- Initialize residual ---*/
125 
126  RhoRes_New = EPS;
127  RhoRes_Old = new su2double[config->GetnZone()];
128  for (iZone = 0; iZone < config->GetnZone(); iZone++) RhoRes_Old[iZone] = EPS;
129 
130  wrote_Paraview_base = false;
131 
132  /*--- Initialize turbo flag ---*/
133  turbo = config->GetBoolTurbomachinery();
134 
135  if(turbo){
136  /*--- Initializate quantities for turboperformace ---*/
137  nSpanWiseSections = config->GetnSpanMaxAllZones();
138  nMarkerTurboPerf = config->GetnMarker_TurboPerformance();
139 
140 
141  TotalStaticEfficiency = new su2double*[nMarkerTurboPerf];
142  TotalTotalEfficiency = new su2double*[nMarkerTurboPerf];
143  KineticEnergyLoss = new su2double*[nMarkerTurboPerf];
144  TRadius = new su2double*[nMarkerTurboPerf];
145  TotalPressureLoss = new su2double*[nMarkerTurboPerf];
146  MassFlowIn = new su2double*[nMarkerTurboPerf];
147  MassFlowOut = new su2double*[nMarkerTurboPerf];
148  FlowAngleIn = new su2double*[nMarkerTurboPerf];
149  FlowAngleIn_BC = new su2double*[nMarkerTurboPerf];
150  FlowAngleOut = new su2double*[nMarkerTurboPerf];
151  EulerianWork = new su2double*[nMarkerTurboPerf];
152  TotalEnthalpyIn = new su2double*[nMarkerTurboPerf];
153  TotalEnthalpyIn_BC = new su2double*[nMarkerTurboPerf];
154  EntropyIn = new su2double*[nMarkerTurboPerf];
155  EntropyOut = new su2double*[nMarkerTurboPerf];
156  EntropyIn_BC = new su2double*[nMarkerTurboPerf];
157  PressureRatio = new su2double*[nMarkerTurboPerf];
158  TotalTemperatureIn = new su2double*[nMarkerTurboPerf];
159  EnthalpyOut = new su2double*[nMarkerTurboPerf];
160  MachIn = new su2double**[nMarkerTurboPerf];
161  MachOut = new su2double**[nMarkerTurboPerf];
162  VelocityOutIs = new su2double*[nMarkerTurboPerf];
163  DensityIn = new su2double*[nMarkerTurboPerf];
164  PressureIn = new su2double*[nMarkerTurboPerf];
165  TurboVelocityIn = new su2double**[nMarkerTurboPerf];
166  DensityOut = new su2double*[nMarkerTurboPerf];
167  PressureOut = new su2double*[nMarkerTurboPerf];
168  TurboVelocityOut = new su2double**[nMarkerTurboPerf];
169  EnthalpyOutIs = new su2double*[nMarkerTurboPerf];
170  EntropyGen = new su2double*[nMarkerTurboPerf];
171  AbsFlowAngleIn = new su2double*[nMarkerTurboPerf];
172  TotalEnthalpyOut = new su2double*[nMarkerTurboPerf];
173  TotalEnthalpyOutIs = new su2double*[nMarkerTurboPerf];
174  RothalpyIn = new su2double*[nMarkerTurboPerf];
175  RothalpyOut = new su2double*[nMarkerTurboPerf];
176  AbsFlowAngleOut = new su2double*[nMarkerTurboPerf];
177  PressureOut_BC = new su2double*[nMarkerTurboPerf];
178  TemperatureIn = new su2double*[nMarkerTurboPerf];
179  TemperatureOut = new su2double*[nMarkerTurboPerf];
180  TotalPressureIn = new su2double*[nMarkerTurboPerf];
181  TotalPressureOut = new su2double*[nMarkerTurboPerf];
182  TotalTemperatureOut = new su2double*[nMarkerTurboPerf];
183  EnthalpyIn = new su2double*[nMarkerTurboPerf];
184  TurbIntensityIn = new su2double*[nMarkerTurboPerf];
185  Turb2LamViscRatioIn = new su2double*[nMarkerTurboPerf];
186  TurbIntensityOut = new su2double*[nMarkerTurboPerf];
187  Turb2LamViscRatioOut = new su2double*[nMarkerTurboPerf];
188  NuFactorIn = new su2double*[nMarkerTurboPerf];
189  NuFactorOut = new su2double*[nMarkerTurboPerf];
190 
191  for (iMarker = 0; iMarker < nMarkerTurboPerf; iMarker++){
192  TotalStaticEfficiency [iMarker] = new su2double [nSpanWiseSections + 1];
193  TotalTotalEfficiency [iMarker] = new su2double [nSpanWiseSections + 1];
194  KineticEnergyLoss [iMarker] = new su2double [nSpanWiseSections + 1];
195  TRadius [iMarker] = new su2double [nSpanWiseSections + 1];
196  TotalPressureLoss [iMarker] = new su2double [nSpanWiseSections + 1];
197  MassFlowIn [iMarker] = new su2double [nSpanWiseSections + 1];
198  MassFlowOut [iMarker] = new su2double [nSpanWiseSections + 1];
199  FlowAngleIn [iMarker] = new su2double [nSpanWiseSections + 1];
200  FlowAngleIn_BC [iMarker] = new su2double [nSpanWiseSections + 1];
201  FlowAngleOut [iMarker] = new su2double [nSpanWiseSections + 1];
202  EulerianWork [iMarker] = new su2double [nSpanWiseSections + 1];
203  TotalEnthalpyIn [iMarker] = new su2double [nSpanWiseSections + 1];
204  TotalEnthalpyIn_BC [iMarker] = new su2double [nSpanWiseSections + 1];
205  EntropyIn [iMarker] = new su2double [nSpanWiseSections + 1];
206  EntropyOut [iMarker] = new su2double [nSpanWiseSections + 1];
207  EntropyIn_BC [iMarker] = new su2double [nSpanWiseSections + 1];
208  PressureRatio [iMarker] = new su2double [nSpanWiseSections + 1];
209  TotalTemperatureIn [iMarker] = new su2double [nSpanWiseSections + 1];
210  EnthalpyOut [iMarker] = new su2double [nSpanWiseSections + 1];
211  MachIn [iMarker] = new su2double*[nSpanWiseSections + 1];
212  MachOut [iMarker] = new su2double*[nSpanWiseSections + 1];
213  VelocityOutIs [iMarker] = new su2double [nSpanWiseSections + 1];
214  DensityIn [iMarker] = new su2double [nSpanWiseSections + 1];
215  PressureIn [iMarker] = new su2double [nSpanWiseSections + 1];
216  TurboVelocityIn [iMarker] = new su2double*[nSpanWiseSections + 1];
217  DensityOut [iMarker] = new su2double [nSpanWiseSections + 1];
218  PressureOut [iMarker] = new su2double [nSpanWiseSections + 1];
219  TurboVelocityOut [iMarker] = new su2double*[nSpanWiseSections + 1];
220  EnthalpyOutIs [iMarker] = new su2double [nSpanWiseSections + 1];
221  EntropyGen [iMarker] = new su2double [nSpanWiseSections + 1];
222  AbsFlowAngleIn [iMarker] = new su2double [nSpanWiseSections + 1];
223  TotalEnthalpyOut [iMarker] = new su2double [nSpanWiseSections + 1];
224  TotalEnthalpyOutIs [iMarker] = new su2double [nSpanWiseSections + 1];
225  RothalpyIn [iMarker] = new su2double [nSpanWiseSections + 1];
226  RothalpyOut [iMarker] = new su2double [nSpanWiseSections + 1];
227  AbsFlowAngleOut [iMarker] = new su2double [nSpanWiseSections + 1];
228  PressureOut_BC [iMarker] = new su2double [nSpanWiseSections + 1];
229  TemperatureIn [iMarker] = new su2double [nSpanWiseSections + 1];
230  TemperatureOut [iMarker] = new su2double [nSpanWiseSections + 1];
231  TotalPressureIn [iMarker] = new su2double [nSpanWiseSections + 1];
232  TotalPressureOut [iMarker] = new su2double [nSpanWiseSections + 1];
233  TotalTemperatureOut [iMarker] = new su2double [nSpanWiseSections + 1];
234  EnthalpyIn [iMarker] = new su2double [nSpanWiseSections + 1];
235  TurbIntensityIn [iMarker] = new su2double [nSpanWiseSections + 1];
236  Turb2LamViscRatioIn [iMarker] = new su2double [nSpanWiseSections + 1];
237  TurbIntensityOut [iMarker] = new su2double [nSpanWiseSections + 1];
238  Turb2LamViscRatioOut [iMarker] = new su2double [nSpanWiseSections + 1];
239  NuFactorIn [iMarker] = new su2double [nSpanWiseSections + 1];
240  NuFactorOut [iMarker] = new su2double [nSpanWiseSections + 1];
241 
242 
243  for (iSpan = 0; iSpan < nSpanWiseSections + 1; iSpan++){
244  TotalStaticEfficiency [iMarker][iSpan] = 0.0;
245  TotalTotalEfficiency [iMarker][iSpan] = 0.0;
246  KineticEnergyLoss [iMarker][iSpan] = 0.0;
247  TRadius [iMarker][iSpan] = 0.0;
248  TotalPressureLoss [iMarker][iSpan] = 0.0;
249  MassFlowIn [iMarker][iSpan] = 0.0;
250  MassFlowOut [iMarker][iSpan] = 0.0;
251  FlowAngleIn [iMarker][iSpan] = 0.0;
252  FlowAngleIn_BC [iMarker][iSpan] = config->GetFlowAngleIn_BC();
253  FlowAngleOut [iMarker][iSpan] = 0.0;
254  EulerianWork [iMarker][iSpan] = 0.0;
255  TotalEnthalpyIn [iMarker][iSpan] = 0.0;
256  TotalEnthalpyIn_BC [iMarker][iSpan] = 0.0;
257  EntropyIn [iMarker][iSpan] = 0.0;
258  EntropyOut [iMarker][iSpan] = 0.0;
259  EntropyIn_BC [iMarker][iSpan] = 0.0;
260  PressureRatio [iMarker][iSpan] = 0.0;
261  TotalTemperatureIn [iMarker][iSpan] = 0.0;
262  EnthalpyOut [iMarker][iSpan] = 0.0;
263 
264 
265  VelocityOutIs [iMarker][iSpan] = 0.0;
266  DensityIn [iMarker][iSpan] = 0.0;
267  PressureIn [iMarker][iSpan] = 0.0;
268 
269  DensityOut [iMarker][iSpan] = 0.0;
270  PressureOut [iMarker][iSpan] = 0.0;
271 
272  EnthalpyOutIs [iMarker][iSpan] = 0.0;
273  EntropyGen [iMarker][iSpan] = 0.0;
274  AbsFlowAngleIn [iMarker][iSpan] = 0.0;
275  TotalEnthalpyOut [iMarker][iSpan] = 0.0;
276  TotalEnthalpyOutIs [iMarker][iSpan] = 0.0;
277  RothalpyIn [iMarker][iSpan] = 0.0;
278  RothalpyOut [iMarker][iSpan] = 0.0;
279  AbsFlowAngleOut [iMarker][iSpan] = 0.0;
280  PressureOut_BC [iMarker][iSpan] = config->GetPressureOut_BC();
281 
282  TemperatureIn [iMarker][iSpan] = 0.0;
283  TemperatureOut [iMarker][iSpan] = 0.0;
284  TotalPressureIn [iMarker][iSpan] = 0.0;
285  TotalPressureOut [iMarker][iSpan] = 0.0;
286  TotalTemperatureOut [iMarker][iSpan] = 0.0;
287  EnthalpyIn [iMarker][iSpan] = 0.0;
288  TurbIntensityIn [iMarker][iSpan] = 0.0;
289  Turb2LamViscRatioIn [iMarker][iSpan] = 0.0;
290  TurbIntensityOut [iMarker][iSpan] = 0.0;
291  Turb2LamViscRatioOut [iMarker][iSpan] = 0.0;
292  NuFactorIn [iMarker][iSpan] = 0.0;
293  NuFactorOut [iMarker][iSpan] = 0.0;
294  MachIn [iMarker][iSpan] = new su2double[4];
295  MachOut [iMarker][iSpan] = new su2double[4];
296  TurboVelocityIn [iMarker][iSpan] = new su2double[4];
297  TurboVelocityOut [iMarker][iSpan] = new su2double[4];
298 
299  for (iDim = 0; iDim < 4; iDim++){
300  MachIn [iMarker][iSpan][iDim] = 0.0;
301  MachOut [iMarker][iSpan][iDim] = 0.0;
302  TurboVelocityIn [iMarker][iSpan][iDim] = 0.0;
303  TurboVelocityOut [iMarker][iSpan][iDim] = 0.0;
304  }
305  }
306  }
307  }
308 }
309 
311  /* delete pointers initialized at construction*/
312  /* Coords and Conn_*(Connectivity) have their own dealloc functions */
313  /* Data is taken care of in DeallocateSolution function */
314 
315  if (RhoRes_Old != NULL) delete [] RhoRes_Old;
316 
317  /*--- Delete turboperformance pointers initiliazed at constrction ---*/
318  unsigned short iMarker, iSpan;
319  if(turbo){
320  for(iMarker = 0; iMarker< nMarkerTurboPerf; iMarker++){
321  for(iSpan=0; iSpan<nSpanWiseSections+1; iSpan++){
322  delete [] MachIn [iMarker][iSpan];
323  delete [] MachOut [iMarker][iSpan];
324  delete [] TurboVelocityIn [iMarker][iSpan];
325  delete [] TurboVelocityOut[iMarker][iSpan];
326  }
327  }
328  for(iMarker = 0; iMarker< nMarkerTurboPerf; iMarker++){
329  delete [] TotalStaticEfficiency[iMarker];
330  delete [] TotalTotalEfficiency [iMarker];
331  delete [] KineticEnergyLoss [iMarker];
332  delete [] TRadius [iMarker];
333  delete [] TotalPressureLoss [iMarker];
334  delete [] MassFlowIn [iMarker];
335  delete [] MassFlowOut [iMarker];
336  delete [] FlowAngleIn [iMarker];
337  delete [] FlowAngleOut [iMarker];
338  delete [] EulerianWork [iMarker];
339  delete [] TotalEnthalpyIn [iMarker];
340  delete [] TotalEnthalpyOut [iMarker];
341  delete [] TotalEnthalpyOutIs [iMarker];
342  delete [] PressureRatio [iMarker];
343  delete [] EnthalpyOut [iMarker];
344  delete [] VelocityOutIs [iMarker];
345  delete [] TotalTemperatureIn [iMarker];
346  delete [] FlowAngleIn_BC [iMarker];
347  delete [] EntropyIn [iMarker];
348  delete [] EntropyIn_BC [iMarker];
349  delete [] EntropyOut [iMarker];
350  delete [] TotalEnthalpyIn_BC [iMarker];
351  delete [] DensityIn [iMarker];
352  delete [] PressureIn [iMarker];
353  delete [] DensityOut [iMarker];
354  delete [] PressureOut [iMarker];
355  delete [] EnthalpyOutIs [iMarker];
356  delete [] EntropyGen [iMarker];
357  delete [] AbsFlowAngleIn [iMarker];
358  delete [] RothalpyIn [iMarker];
359  delete [] RothalpyOut [iMarker];
360  delete [] AbsFlowAngleOut [iMarker];
361  delete [] PressureOut_BC [iMarker];
362  delete [] MachIn [iMarker];
363  delete [] MachOut [iMarker];
364  delete [] TurboVelocityIn [iMarker];
365  delete [] TurboVelocityOut [iMarker];
366  delete [] TemperatureIn [iMarker];
367  delete [] TemperatureOut [iMarker];
368  delete [] TotalPressureIn [iMarker];
369  delete [] TotalPressureOut [iMarker];
370  delete [] TotalTemperatureOut [iMarker];
371  delete [] EnthalpyIn [iMarker];
372  delete [] TurbIntensityIn [iMarker];
373  delete [] Turb2LamViscRatioIn [iMarker];
374  delete [] TurbIntensityOut [iMarker];
375  delete [] Turb2LamViscRatioOut [iMarker];
376  delete [] NuFactorIn [iMarker];
377  delete [] NuFactorOut [iMarker];
378 
379 
380  }
381  delete [] TotalStaticEfficiency;
382  delete [] TotalTotalEfficiency;
383  delete [] KineticEnergyLoss;
384  delete [] TRadius;
385  delete [] TotalPressureLoss;
386  delete [] MassFlowIn;
387  delete [] MassFlowOut;
388  delete [] FlowAngleIn;
389  delete [] FlowAngleOut;
390  delete [] EulerianWork;
391  delete [] TotalEnthalpyIn;
392  delete [] TotalEnthalpyOut;
393  delete [] TotalEnthalpyOutIs;
394  delete [] PressureRatio;
395  delete [] EnthalpyOut;
396  delete [] VelocityOutIs;
397  delete [] TotalTemperatureIn;
398  delete [] FlowAngleIn_BC;
399  delete [] EntropyIn;
400  delete [] EntropyIn_BC;
401  delete [] EntropyOut;
402  delete [] TotalEnthalpyIn_BC;
403  delete [] DensityIn;
404  delete [] PressureIn;
405  delete [] DensityOut;
406  delete [] PressureOut;
407  delete [] EnthalpyOutIs;
408  delete [] EntropyGen;
409  delete [] AbsFlowAngleIn;
410  delete [] RothalpyIn;
411  delete [] RothalpyOut;
412  delete [] AbsFlowAngleOut;
413  delete [] PressureOut_BC;
414  delete [] MachIn;
415  delete [] MachOut;
416  delete [] TurboVelocityIn;
417  delete [] TurboVelocityOut;
418  delete [] TemperatureIn;
419  delete [] TemperatureOut;
420  delete [] TotalPressureIn;
421  delete [] TotalPressureOut;
422  delete [] TotalTemperatureOut;
423  delete [] EnthalpyIn;
424  delete [] TurbIntensityIn;
425  delete [] Turb2LamViscRatioIn;
426  delete [] TurbIntensityOut;
427  delete [] Turb2LamViscRatioOut;
428  delete [] NuFactorIn;
429  delete [] NuFactorOut;
430  }
431 }
432 
434  CSolver *FlowSolver, unsigned long iExtIter,
435  unsigned short val_iZone, unsigned short val_iInst) {
436 
437  unsigned short iMarker;
438  unsigned long iPoint, iVertex, Global_Index;
439  su2double PressCoeff = 0.0, SkinFrictionCoeff[3], HeatFlux;
440  su2double xCoord = 0.0, yCoord = 0.0, zCoord = 0.0, Mach, Pressure;
441  char cstr[200];
442 
443  unsigned short solver = config->GetKind_Solver();
444  unsigned short nDim = geometry->GetnDim();
445 
446 #ifndef HAVE_MPI
447 
448  unsigned short iDim;
449  char buffer [50];
450  ofstream SurfFlow_file;
451 
452  /*--- Write file name with extension if unsteady ---*/
453  strcpy (cstr, config->GetSurfCoeff_FileName().c_str());
454 
455  if (config->GetTime_Marching() == HARMONIC_BALANCE) {
456  SPRINTF (buffer, "_%d.csv", SU2_TYPE::Int(val_iInst));
457 
458  }else if (config->GetTime_Marching() && config->GetTime_Domain()) {
459  if ((SU2_TYPE::Int(iExtIter) >= 0) && (SU2_TYPE::Int(iExtIter) < 10)) SPRINTF (buffer, "_0000%d.csv", SU2_TYPE::Int(iExtIter));
460  if ((SU2_TYPE::Int(iExtIter) >= 10) && (SU2_TYPE::Int(iExtIter) < 100)) SPRINTF (buffer, "_000%d.csv", SU2_TYPE::Int(iExtIter));
461  if ((SU2_TYPE::Int(iExtIter) >= 100) && (SU2_TYPE::Int(iExtIter) < 1000)) SPRINTF (buffer, "_00%d.csv", SU2_TYPE::Int(iExtIter));
462  if ((SU2_TYPE::Int(iExtIter) >= 1000) && (SU2_TYPE::Int(iExtIter) < 10000)) SPRINTF (buffer, "_0%d.csv", SU2_TYPE::Int(iExtIter));
463  if (SU2_TYPE::Int(iExtIter) >= 10000) SPRINTF (buffer, "_%d.csv", SU2_TYPE::Int(iExtIter));
464  }
465  else
466  SPRINTF (buffer, ".csv");
467 
468  strcat (cstr, buffer);
469  SurfFlow_file.precision(15);
470  SurfFlow_file.open(cstr, ios::out);
471 
472  SurfFlow_file << "\"Global_Index\", \"x_coord\", \"y_coord\", ";
473  if (nDim == 3) SurfFlow_file << "\"z_coord\", ";
474  SurfFlow_file << "\"Pressure\", \"Pressure_Coefficient\", ";
475 
476  switch (solver) {
477  case EULER : case INC_EULER: SurfFlow_file << "\"Mach_Number\"" << "\n"; break;
478  case NAVIER_STOKES: case RANS: case INC_NAVIER_STOKES: case INC_RANS:
479  if (nDim == 2) SurfFlow_file << "\"Skin_Friction_Coefficient_X\", \"Skin_Friction_Coefficient_Y\", \"Heat_Flux\"" << "\n";
480  if (nDim == 3) SurfFlow_file << "\"Skin_Friction_Coefficient_X\", \"Skin_Friction_Coefficient_Y\", \"Skin_Friction_Coefficient_Z\", \"Heat_Flux\"" << "\n";
481  break;
482  }
483 
484  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
485  if (config->GetMarker_All_Plotting(iMarker) == YES) {
486  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
487  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
488  Global_Index = geometry->node[iPoint]->GetGlobalIndex();
489  xCoord = geometry->node[iPoint]->GetCoord(0);
490  yCoord = geometry->node[iPoint]->GetCoord(1);
491  if (nDim == 3) zCoord = geometry->node[iPoint]->GetCoord(2);
492 
493  /*--- The output should be in inches ---*/
494 
495  if (config->GetSystemMeasurements() == US) {
496  xCoord *= 12.0; yCoord *= 12.0;
497  if (nDim == 3) zCoord *= 12.0;
498  }
499 
500  Pressure = FlowSolver->GetNodes()->GetPressure(iPoint);
501  PressCoeff = FlowSolver->GetCPressure(iMarker, iVertex);
502  SurfFlow_file << scientific << Global_Index << ", " << xCoord << ", " << yCoord << ", ";
503  if (nDim == 3) SurfFlow_file << scientific << zCoord << ", ";
504  SurfFlow_file << scientific << Pressure << ", " << PressCoeff << ", ";
505  switch (solver) {
506  case EULER : case FEM_EULER: case INC_EULER:
507  Mach = sqrt(FlowSolver->GetNodes()->GetVelocity2(iPoint)) / FlowSolver->GetNodes()->GetSoundSpeed(iPoint);
508  SurfFlow_file << scientific << Mach << "\n";
509  break;
510  case NAVIER_STOKES: case RANS: case FEM_NAVIER_STOKES: case FEM_RANS: case FEM_LES:
511  case INC_NAVIER_STOKES: case INC_RANS:
512  for (iDim = 0; iDim < nDim; iDim++)
513  SkinFrictionCoeff[iDim] = FlowSolver->GetCSkinFriction(iMarker, iVertex, iDim);
514  HeatFlux = FlowSolver->GetHeatFlux(iMarker, iVertex);
515 
516  if (nDim == 2) SurfFlow_file << scientific << SkinFrictionCoeff[0] << ", " << SkinFrictionCoeff[1] << ", " << HeatFlux << "\n";
517  if (nDim == 3) SurfFlow_file << scientific << SkinFrictionCoeff[0] << ", " << SkinFrictionCoeff[1] << ", " << SkinFrictionCoeff[2] << ", " << HeatFlux << "\n";
518 
519  break;
520  }
521  }
522  }
523  }
524 
525  SurfFlow_file.close();
526 
527 #else
528 
529  int iProcessor, nProcessor = size;
530 
531  unsigned long Buffer_Send_nVertex[1], *Buffer_Recv_nVertex = NULL;
532  unsigned long nVertex_Surface = 0, nLocalVertex_Surface = 0;
533  unsigned long MaxLocalVertex_Surface = 0;
534 
535  /*--- Find the max number of surface vertices among all
536  partitions and set up buffers. The master node will handle the
537  writing of the CSV file after gathering all of the data. ---*/
538 
539  nLocalVertex_Surface = 0;
540  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++)
541  if (config->GetMarker_All_Plotting(iMarker) == YES)
542  for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
543  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
544  if (geometry->node[iPoint]->GetDomain()) nLocalVertex_Surface++;
545  }
546 
547  /*--- Communicate the number of local vertices on each partition
548  to the master node ---*/
549 
550  Buffer_Send_nVertex[0] = nLocalVertex_Surface;
551  if (rank == MASTER_NODE) Buffer_Recv_nVertex = new unsigned long [nProcessor];
552 
553  SU2_MPI::Allreduce(&nLocalVertex_Surface, &MaxLocalVertex_Surface, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
554  SU2_MPI::Gather(&Buffer_Send_nVertex, 1, MPI_UNSIGNED_LONG, Buffer_Recv_nVertex, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
555 
556  /*--- Send and Recv buffers ---*/
557 
558  su2double *Buffer_Send_Coord_x = new su2double [MaxLocalVertex_Surface];
559  su2double *Buffer_Recv_Coord_x = NULL;
560 
561  su2double *Buffer_Send_Coord_y = new su2double [MaxLocalVertex_Surface];
562  su2double *Buffer_Recv_Coord_y = NULL;
563 
564  su2double *Buffer_Send_Coord_z = new su2double [MaxLocalVertex_Surface];
565  su2double *Buffer_Recv_Coord_z = NULL;
566 
567  su2double *Buffer_Send_Press = new su2double [MaxLocalVertex_Surface];
568  su2double *Buffer_Recv_Press = NULL;
569 
570  su2double *Buffer_Send_CPress = new su2double [MaxLocalVertex_Surface];
571  su2double *Buffer_Recv_CPress = NULL;
572 
573  su2double *Buffer_Send_Mach = new su2double [MaxLocalVertex_Surface];
574  su2double *Buffer_Recv_Mach = NULL;
575 
576  su2double *Buffer_Send_SkinFriction_x = new su2double [MaxLocalVertex_Surface];
577  su2double *Buffer_Recv_SkinFriction_x = NULL;
578 
579  su2double *Buffer_Send_SkinFriction_y = new su2double [MaxLocalVertex_Surface];
580  su2double *Buffer_Recv_SkinFriction_y = NULL;
581 
582  su2double *Buffer_Send_SkinFriction_z = new su2double [MaxLocalVertex_Surface];
583  su2double *Buffer_Recv_SkinFriction_z = NULL;
584 
585  su2double *Buffer_Send_HeatTransfer = new su2double [MaxLocalVertex_Surface];
586  su2double *Buffer_Recv_HeatTransfer = NULL;
587 
588  unsigned long *Buffer_Send_GlobalIndex = new unsigned long [MaxLocalVertex_Surface];
589  unsigned long *Buffer_Recv_GlobalIndex = NULL;
590 
591  /*--- Prepare the receive buffers on the master node only. ---*/
592 
593  if (rank == MASTER_NODE) {
594  Buffer_Recv_Coord_x = new su2double [nProcessor*MaxLocalVertex_Surface];
595  Buffer_Recv_Coord_y = new su2double [nProcessor*MaxLocalVertex_Surface];
596  if (nDim == 3) Buffer_Recv_Coord_z = new su2double [nProcessor*MaxLocalVertex_Surface];
597  Buffer_Recv_Press = new su2double [nProcessor*MaxLocalVertex_Surface];
598  Buffer_Recv_CPress = new su2double [nProcessor*MaxLocalVertex_Surface];
599  Buffer_Recv_Mach = new su2double [nProcessor*MaxLocalVertex_Surface];
600  Buffer_Recv_SkinFriction_x = new su2double [nProcessor*MaxLocalVertex_Surface];
601  Buffer_Recv_SkinFriction_y = new su2double [nProcessor*MaxLocalVertex_Surface];
602  if (nDim == 3) Buffer_Recv_SkinFriction_z = new su2double [nProcessor*MaxLocalVertex_Surface];
603  Buffer_Recv_HeatTransfer = new su2double [nProcessor*MaxLocalVertex_Surface];
604  Buffer_Recv_GlobalIndex = new unsigned long [nProcessor*MaxLocalVertex_Surface];
605  }
606 
607  /*--- Loop over all vertices in this partition and load the
608  data of the specified type into the buffer to be sent to
609  the master node. ---*/
610 
611  nVertex_Surface = 0;
612  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++)
613  if (config->GetMarker_All_Plotting(iMarker) == YES)
614  for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
615  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
616  if (geometry->node[iPoint]->GetDomain()) {
617  Buffer_Send_Press[nVertex_Surface] = FlowSolver->GetNodes()->GetPressure(iPoint);
618  Buffer_Send_CPress[nVertex_Surface] = FlowSolver->GetCPressure(iMarker, iVertex);
619  Buffer_Send_Coord_x[nVertex_Surface] = geometry->node[iPoint]->GetCoord(0);
620  Buffer_Send_Coord_y[nVertex_Surface] = geometry->node[iPoint]->GetCoord(1);
621  if (nDim == 3) { Buffer_Send_Coord_z[nVertex_Surface] = geometry->node[iPoint]->GetCoord(2); }
622 
623  /*--- If US system, the output should be in inches ---*/
624 
625  if (config->GetSystemMeasurements() == US) {
626  Buffer_Send_Coord_x[nVertex_Surface] *= 12.0;
627  Buffer_Send_Coord_y[nVertex_Surface] *= 12.0;
628  if (nDim == 3) Buffer_Send_Coord_z[nVertex_Surface] *= 12.0;
629  }
630 
631  Buffer_Send_GlobalIndex[nVertex_Surface] = geometry->node[iPoint]->GetGlobalIndex();
632 
633  if (solver == EULER || solver == FEM_EULER || solver == INC_EULER)
634  Buffer_Send_Mach[nVertex_Surface] = sqrt(FlowSolver->GetNodes()->GetVelocity2(iPoint)) / FlowSolver->GetNodes()->GetSoundSpeed(iPoint);
635 
636  if (solver == NAVIER_STOKES || solver == RANS || solver == INC_NAVIER_STOKES || solver == INC_RANS ||
637  solver == FEM_NAVIER_STOKES || solver == FEM_RANS || solver == FEM_LES) {
638  Buffer_Send_SkinFriction_x[nVertex_Surface] = FlowSolver->GetCSkinFriction(iMarker, iVertex, 0);
639  Buffer_Send_SkinFriction_y[nVertex_Surface] = FlowSolver->GetCSkinFriction(iMarker, iVertex, 1);
640  if (nDim == 3) Buffer_Send_SkinFriction_z[nVertex_Surface] = FlowSolver->GetCSkinFriction(iMarker, iVertex, 2);
641  Buffer_Send_HeatTransfer[nVertex_Surface] = FlowSolver->GetHeatFlux(iMarker, iVertex);
642  }
643  nVertex_Surface++;
644  }
645  }
646 
647  /*--- Send the information to the master node ---*/
648 
649  SU2_MPI::Gather(Buffer_Send_Coord_x, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_Coord_x, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
650  SU2_MPI::Gather(Buffer_Send_Coord_y, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_Coord_y, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
651  if (nDim == 3) SU2_MPI::Gather(Buffer_Send_Coord_z, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_Coord_z, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
652  SU2_MPI::Gather(Buffer_Send_Press, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_Press, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
653  SU2_MPI::Gather(Buffer_Send_CPress, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_CPress, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
654  if (solver == EULER || solver == FEM_EULER || solver == INC_EULER) SU2_MPI::Gather(Buffer_Send_Mach, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_Mach, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
655  if ((solver == NAVIER_STOKES) || (solver == RANS) || (solver == FEM_NAVIER_STOKES) || (solver == FEM_RANS) || (solver == FEM_LES) || (solver == INC_RANS) || (solver == INC_NAVIER_STOKES)) {
656  SU2_MPI::Gather(Buffer_Send_SkinFriction_x, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_SkinFriction_x, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
657  SU2_MPI::Gather(Buffer_Send_SkinFriction_y, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_SkinFriction_y, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
658  if (nDim == 3) SU2_MPI::Gather(Buffer_Send_SkinFriction_z, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_SkinFriction_z, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
659  SU2_MPI::Gather(Buffer_Send_HeatTransfer, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_HeatTransfer, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
660  }
661  SU2_MPI::Gather(Buffer_Send_GlobalIndex, MaxLocalVertex_Surface, MPI_UNSIGNED_LONG, Buffer_Recv_GlobalIndex, MaxLocalVertex_Surface, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
662 
663  /*--- The master node unpacks the data and writes the surface CSV file ---*/
664 
665  if (rank == MASTER_NODE) {
666 
667  /*--- Write file name with extension if unsteady ---*/
668  char buffer[50];
669  string filename = config->GetSurfCoeff_FileName();
670  ofstream SurfFlow_file;
671 
672  /*--- Write file name with extension if unsteady ---*/
673  strcpy (cstr, filename.c_str());
674  if (config->GetTime_Marching() == HARMONIC_BALANCE) {
675  SPRINTF (buffer, "_%d.csv", SU2_TYPE::Int(val_iInst));
676 
677  } else if (config->GetTime_Marching() && config->GetTime_Domain()) {
678  if ((SU2_TYPE::Int(iExtIter) >= 0) && (SU2_TYPE::Int(iExtIter) < 10)) SPRINTF (buffer, "_0000%d.csv", SU2_TYPE::Int(iExtIter));
679  if ((SU2_TYPE::Int(iExtIter) >= 10) && (SU2_TYPE::Int(iExtIter) < 100)) SPRINTF (buffer, "_000%d.csv", SU2_TYPE::Int(iExtIter));
680  if ((SU2_TYPE::Int(iExtIter) >= 100) && (SU2_TYPE::Int(iExtIter) < 1000)) SPRINTF (buffer, "_00%d.csv", SU2_TYPE::Int(iExtIter));
681  if ((SU2_TYPE::Int(iExtIter) >= 1000) && (SU2_TYPE::Int(iExtIter) < 10000)) SPRINTF (buffer, "_0%d.csv", SU2_TYPE::Int(iExtIter));
682  if (SU2_TYPE::Int(iExtIter) >= 10000) SPRINTF (buffer, "_%d.csv", SU2_TYPE::Int(iExtIter));
683  }
684  else
685  SPRINTF (buffer, ".csv");
686 
687  strcat (cstr, buffer);
688  SurfFlow_file.precision(15);
689  SurfFlow_file.open(cstr, ios::out);
690 
691  SurfFlow_file << "\"Global_Index\", \"x_coord\", \"y_coord\", ";
692  if (nDim == 3) SurfFlow_file << "\"z_coord\", ";
693  SurfFlow_file << "\"Pressure\", \"Pressure_Coefficient\", ";
694 
695  switch (solver) {
696  case EULER : case FEM_EULER: case INC_EULER: SurfFlow_file << "\"Mach_Number\"" << "\n"; break;
697  case NAVIER_STOKES: case RANS: case FEM_NAVIER_STOKES: case FEM_RANS: case FEM_LES: case INC_NAVIER_STOKES: case INC_RANS:
698  if (nDim == 2) SurfFlow_file << "\"Skin_Friction_Coefficient_X\", \"Skin_Friction_Coefficient_Y\", \"Heat_Flux\"" << "\n";
699  if (nDim == 3) SurfFlow_file << "\"Skin_Friction_Coefficient_X\", \"Skin_Friction_Coefficient_Y\", \"Skin_Friction_Coefficient_Z\", \"Heat_Flux\"" << "\n";
700  break;
701  }
702 
703  /*--- Loop through all of the collected data and write each node's values ---*/
704 
705  unsigned long Total_Index;
706  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
707  for (iVertex = 0; iVertex < Buffer_Recv_nVertex[iProcessor]; iVertex++) {
708 
709  /*--- Current index position and global index ---*/
710  Total_Index = iProcessor*MaxLocalVertex_Surface+iVertex;
711  Global_Index = Buffer_Recv_GlobalIndex[Total_Index];
712 
713  /*--- Retrieve the merged data for this node ---*/
714  xCoord = Buffer_Recv_Coord_x[Total_Index];
715  yCoord = Buffer_Recv_Coord_y[Total_Index];
716  if (nDim == 3) zCoord = Buffer_Recv_Coord_z[Total_Index];
717  Pressure = Buffer_Recv_Press[Total_Index];
718  PressCoeff = Buffer_Recv_CPress[Total_Index];
719 
720  /*--- Write the first part of the data ---*/
721  SurfFlow_file << scientific << Global_Index << ", " << xCoord << ", " << yCoord << ", ";
722  if (nDim == 3) SurfFlow_file << scientific << zCoord << ", ";
723  SurfFlow_file << scientific << Pressure << ", " << PressCoeff << ", ";
724 
725  /*--- Write the solver-dependent part of the data ---*/
726  switch (solver) {
727  case EULER :
728  case FEM_EULER:
729  case INC_EULER:
730  Mach = Buffer_Recv_Mach[Total_Index];
731  SurfFlow_file << scientific << Mach << "\n";
732  break;
733  case NAVIER_STOKES: case RANS:
734  case FEM_NAVIER_STOKES: case FEM_RANS: case FEM_LES:
735  case INC_NAVIER_STOKES: case INC_RANS:
736  SkinFrictionCoeff[0] = Buffer_Recv_SkinFriction_x[Total_Index];
737  SkinFrictionCoeff[1] = Buffer_Recv_SkinFriction_y[Total_Index];
738  if (nDim == 3) SkinFrictionCoeff[2] = Buffer_Recv_SkinFriction_z[Total_Index];
739  HeatFlux = Buffer_Recv_HeatTransfer[Total_Index];
740  if (nDim == 2) SurfFlow_file << scientific << SkinFrictionCoeff[0] << ", " << SkinFrictionCoeff[1] << ", " << HeatFlux << "\n";
741  if (nDim == 3) SurfFlow_file << scientific << SkinFrictionCoeff[0] << ", " << SkinFrictionCoeff[1] << ", " << SkinFrictionCoeff[2] << ", " << HeatFlux << "\n";
742  break;
743  }
744  }
745  }
746 
747  /*--- Close the CSV file ---*/
748  SurfFlow_file.close();
749 
750  /*--- Release the recv buffers on the master node ---*/
751 
752  delete [] Buffer_Recv_Coord_x;
753  delete [] Buffer_Recv_Coord_y;
754  if (nDim == 3) delete [] Buffer_Recv_Coord_z;
755  delete [] Buffer_Recv_Press;
756  delete [] Buffer_Recv_CPress;
757  delete [] Buffer_Recv_Mach;
758  delete [] Buffer_Recv_SkinFriction_x;
759  delete [] Buffer_Recv_SkinFriction_y;
760  if (nDim == 3) delete [] Buffer_Recv_SkinFriction_z;
761  delete [] Buffer_Recv_HeatTransfer;
762  delete [] Buffer_Recv_GlobalIndex;
763 
764  delete [] Buffer_Recv_nVertex;
765 
766  }
767 
768  /*--- Release the memory for the remaining buffers and exit ---*/
769 
770  delete [] Buffer_Send_Coord_x;
771  delete [] Buffer_Send_Coord_y;
772  delete [] Buffer_Send_Coord_z;
773  delete [] Buffer_Send_Press;
774  delete [] Buffer_Send_CPress;
775  delete [] Buffer_Send_Mach;
776  delete [] Buffer_Send_SkinFriction_x;
777  delete [] Buffer_Send_SkinFriction_y;
778  delete [] Buffer_Send_SkinFriction_z;
779  delete [] Buffer_Send_HeatTransfer;
780  delete [] Buffer_Send_GlobalIndex;
781 
782 #endif
783 
784 }
785 
786 void COutputLegacy::SetSurfaceCSV_Adjoint(CConfig *config, CGeometry *geometry, CSolver *AdjSolver, CSolver *FlowSolution, unsigned long iExtIter, unsigned short val_iZone, unsigned short val_iInst) {
787 
788 #ifndef HAVE_MPI
789 
790  unsigned long iPoint, iVertex, Global_Index;
791  su2double *Solution, xCoord, yCoord, zCoord;
792  unsigned short iMarker;
793  char cstr[200], buffer[50];
794  ofstream SurfAdj_file;
795 
796  /*--- Write file name with extension if unsteady ---*/
797 
798  strcpy (cstr, config->GetSurfAdjCoeff_FileName().c_str());
799 
800  if (config->GetTime_Marching() == HARMONIC_BALANCE) {
801  SPRINTF (buffer, "_%d.csv", SU2_TYPE::Int(val_iInst));
802 
803  } else if (config->GetTime_Marching() && config->GetTime_Domain()) {
804  if ((SU2_TYPE::Int(iExtIter) >= 0) && (SU2_TYPE::Int(iExtIter) < 10)) SPRINTF (buffer, "_0000%d.csv", SU2_TYPE::Int(iExtIter));
805  if ((SU2_TYPE::Int(iExtIter) >= 10) && (SU2_TYPE::Int(iExtIter) < 100)) SPRINTF (buffer, "_000%d.csv", SU2_TYPE::Int(iExtIter));
806  if ((SU2_TYPE::Int(iExtIter) >= 100) && (SU2_TYPE::Int(iExtIter) < 1000)) SPRINTF (buffer, "_00%d.csv", SU2_TYPE::Int(iExtIter));
807  if ((SU2_TYPE::Int(iExtIter) >= 1000) && (SU2_TYPE::Int(iExtIter) < 10000)) SPRINTF (buffer, "_0%d.csv", SU2_TYPE::Int(iExtIter));
808  if (SU2_TYPE::Int(iExtIter) >= 10000) SPRINTF (buffer, "_%d.csv", SU2_TYPE::Int(iExtIter));
809  }
810  else
811  SPRINTF (buffer, ".csv");
812 
813  strcat(cstr, buffer);
814  SurfAdj_file.precision(15);
815  SurfAdj_file.open(cstr, ios::out);
816 
817  SurfAdj_file << "SENS_AOA=" << AdjSolver->GetTotal_Sens_AoA() * PI_NUMBER / 180.0 << endl;
818 
819  if (geometry->GetnDim() == 2) {
820  if (config ->GetKind_Regime() == COMPRESSIBLE)
821  SurfAdj_file << "\"Point\",\"Sensitivity\",\"PsiRho\",\"Phi_x\",\"Phi_y\",\"PsiE\",\"x_coord\",\"y_coord\"";
822  else if (config ->GetKind_Regime() == INCOMPRESSIBLE)
823  SurfAdj_file << "\"Point\",\"Sensitivity\",\"PsiRho\",\"Phi_x\",\"Phi_y\",\"x_coord\",\"y_coord\"";
824 
825  if (config->GetDiscrete_Adjoint()) {
826  SurfAdj_file << ",\"x_Sens\",\"y_Sens\"";
827  }
828  SurfAdj_file << "\n";
829 
830  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
831  if (config->GetMarker_All_Plotting(iMarker) == YES)
832  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
833  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
834  Global_Index = geometry->node[iPoint]->GetGlobalIndex();
835  Solution = AdjSolver->GetNodes()->GetSolution(iPoint);
836  xCoord = geometry->node[iPoint]->GetCoord(0);
837  yCoord = geometry->node[iPoint]->GetCoord(1);
838 
839  /*--- If US system, the output should be in inches ---*/
840 
841  if (config->GetSystemMeasurements() == US) {
842  xCoord *= 12.0;
843  yCoord *= 12.0;
844  }
845  if (config ->GetKind_Regime() == COMPRESSIBLE)
846  SurfAdj_file << scientific << Global_Index << ", " << AdjSolver->GetCSensitivity(iMarker, iVertex) << ", " << Solution[0] << ", "
847  << Solution[1] << ", " << Solution[2] << ", " << Solution[3] <<", " << xCoord <<", "<< yCoord;
848  else if (config ->GetKind_Regime() == INCOMPRESSIBLE)
849  SurfAdj_file << scientific << Global_Index << ", " << AdjSolver->GetCSensitivity(iMarker, iVertex) << ", " << Solution[0] << ", "
850  << Solution[1] << ", " << Solution[2] <<", " << xCoord <<", "<< yCoord;
851  if (config->GetDiscrete_Adjoint()) {
852  SurfAdj_file << ", " << AdjSolver->GetNodes()->GetSensitivity(iPoint,0) << ", " << AdjSolver->GetNodes()->GetSensitivity(iPoint,1);
853  }
854  SurfAdj_file << "\n";
855  }
856  }
857  }
858 
859  if (geometry->GetnDim() == 3) {
860  if (config ->GetKind_Regime() == COMPRESSIBLE)
861  SurfAdj_file << "\"Point\",\"Sensitivity\",\"PsiRho\",\"Phi_x\",\"Phi_y\",\"Phi_z\",\"PsiE\",\"x_coord\",\"y_coord\",\"z_coord\"";
862  else if (config ->GetKind_Regime() == INCOMPRESSIBLE)
863  SurfAdj_file << "\"Point\",\"Sensitivity\",\"PsiRho\",\"Phi_x\",\"Phi_y\",\"Phi_z\",\"x_coord\",\"y_coord\",\"z_coord\"";
864 
865  if (config->GetDiscrete_Adjoint()) {
866  SurfAdj_file << ",\"x_Sens\",\"y_Sens\",\"z_Sens\"";
867  }
868  SurfAdj_file << "\n";
869  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
870  if (config->GetMarker_All_Plotting(iMarker) == YES)
871  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
872  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
873  Global_Index = geometry->node[iPoint]->GetGlobalIndex();
874  Solution = AdjSolver->GetNodes()->GetSolution(iPoint);
875 
876  xCoord = geometry->node[iPoint]->GetCoord(0);
877  yCoord = geometry->node[iPoint]->GetCoord(1);
878  zCoord = geometry->node[iPoint]->GetCoord(2);
879 
880  /*--- If US system, the output should be in inches ---*/
881 
882  if (config->GetSystemMeasurements() == US) {
883  xCoord *= 12.0;
884  yCoord *= 12.0;
885  zCoord *= 12.0;
886  }
887  if (config ->GetKind_Regime() == COMPRESSIBLE)
888  SurfAdj_file << scientific << Global_Index << ", " << AdjSolver->GetCSensitivity(iMarker, iVertex) << ", " << Solution[0] << ", "
889  << Solution[1] << ", " << Solution[2] << ", " << Solution[3] << ", " << Solution[4] << ", "<< xCoord <<", "<< yCoord <<", "<< zCoord;
890  else if (config ->GetKind_Regime() == INCOMPRESSIBLE)
891  SurfAdj_file << scientific << Global_Index << ", " << AdjSolver->GetCSensitivity(iMarker, iVertex) << ", " << Solution[0] << ", "
892  << Solution[1] << ", " << Solution[2] << ", " << Solution[3] << ", " << xCoord <<", "<< yCoord <<", "<< zCoord;
893  if (config->GetDiscrete_Adjoint()) {
894  SurfAdj_file << ", " << AdjSolver->GetNodes()->GetSensitivity(iPoint,0) << ", " << AdjSolver->GetNodes()->GetSensitivity(iPoint,1)
895  << ", " << AdjSolver->GetNodes()->GetSensitivity(iPoint, 2);
896  }
897  SurfAdj_file << "\n";
898  }
899  }
900  }
901 
902  SurfAdj_file.close();
903 
904 #else
905  int iProcessor, nProcessor = size;
906 
907  unsigned short nDim = geometry->GetnDim(), iMarker;
908  su2double *Solution, *Coord;
909  unsigned long Buffer_Send_nVertex[1], iVertex, iPoint, nVertex_Surface = 0, nLocalVertex_Surface = 0,
910  MaxLocalVertex_Surface = 0, nBuffer_Scalar;
911  unsigned long *Buffer_Receive_nVertex = NULL;
912  ofstream SurfAdj_file;
913 
914  /*--- Write the surface .csv file ---*/
915  nLocalVertex_Surface = 0;
916  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++)
917  if (config->GetMarker_All_Plotting(iMarker) == YES)
918  for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
919  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
920  if (geometry->node[iPoint]->GetDomain()) nLocalVertex_Surface ++;
921  }
922 
923  if (rank == MASTER_NODE)
924  Buffer_Receive_nVertex = new unsigned long [nProcessor];
925 
926  Buffer_Send_nVertex[0] = nLocalVertex_Surface;
927 
928  SU2_MPI::Allreduce(&nLocalVertex_Surface, &MaxLocalVertex_Surface, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
929  SU2_MPI::Gather(&Buffer_Send_nVertex, 1, MPI_UNSIGNED_LONG, Buffer_Receive_nVertex, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
930 
931  su2double *Buffer_Send_Coord_x = new su2double[MaxLocalVertex_Surface];
932  su2double *Buffer_Send_Coord_y= new su2double[MaxLocalVertex_Surface];
933  su2double *Buffer_Send_Coord_z= new su2double[MaxLocalVertex_Surface];
934  unsigned long *Buffer_Send_GlobalPoint= new unsigned long[MaxLocalVertex_Surface];
935  su2double *Buffer_Send_Sensitivity= new su2double[MaxLocalVertex_Surface];
936  su2double *Buffer_Send_PsiRho= new su2double[MaxLocalVertex_Surface];
937  su2double *Buffer_Send_Phi_x= new su2double[MaxLocalVertex_Surface];
938  su2double *Buffer_Send_Phi_y= new su2double[MaxLocalVertex_Surface];
939  su2double *Buffer_Send_Phi_z= new su2double[MaxLocalVertex_Surface];
940  su2double *Buffer_Send_PsiE = NULL;
941 
942  if (config ->GetKind_Regime() == COMPRESSIBLE)
943  Buffer_Send_PsiE = new su2double[MaxLocalVertex_Surface];
944 
945  su2double *Buffer_Send_Sens_x = NULL, *Buffer_Send_Sens_y = NULL, *Buffer_Send_Sens_z = NULL;
946 
947  if (config->GetDiscrete_Adjoint()) {
948  Buffer_Send_Sens_x = new su2double[MaxLocalVertex_Surface];
949  Buffer_Send_Sens_y = new su2double[MaxLocalVertex_Surface];
950  if (nDim == 3) {
951  Buffer_Send_Sens_z = new su2double[MaxLocalVertex_Surface];
952  }
953  }
954 
955  nVertex_Surface = 0;
956  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++)
957  if (config->GetMarker_All_Plotting(iMarker) == YES)
958  for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
959  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
960  if (geometry->node[iPoint]->GetDomain()) {
961  Solution = AdjSolver->GetNodes()->GetSolution(iPoint);
962  //Normal = geometry->vertex[iMarker][iVertex]->GetNormal();
963  Coord = geometry->node[iPoint]->GetCoord();
964  //d = AdjSolver->GetNodes()->GetForceProj_Vector(iPoint);
965  Buffer_Send_GlobalPoint[nVertex_Surface] = geometry->node[iPoint]->GetGlobalIndex();
966  Buffer_Send_Coord_x[nVertex_Surface] = Coord[0];
967  Buffer_Send_Coord_y[nVertex_Surface] = Coord[1];
968  Buffer_Send_Sensitivity[nVertex_Surface] = AdjSolver->GetCSensitivity(iMarker, iVertex);
969  Buffer_Send_PsiRho[nVertex_Surface] = Solution[0];
970  Buffer_Send_Phi_x[nVertex_Surface] = Solution[1];
971  Buffer_Send_Phi_y[nVertex_Surface] = Solution[2];
972  if ((nDim == 2) && (config->GetKind_Regime() == COMPRESSIBLE)) Buffer_Send_PsiE[nVertex_Surface] = Solution[3];
973  if (nDim == 3) {
974  Buffer_Send_Coord_z[nVertex_Surface] = Coord[2];
975  Buffer_Send_Phi_z[nVertex_Surface] = Solution[3];
976  if(config->GetKind_Regime() == COMPRESSIBLE) Buffer_Send_PsiE[nVertex_Surface] = Solution[4];
977  }
978  if (config->GetDiscrete_Adjoint()) {
979  Buffer_Send_Sens_x[nVertex_Surface] = AdjSolver->GetNodes()->GetSensitivity(iPoint, 0);
980  Buffer_Send_Sens_y[nVertex_Surface] = AdjSolver->GetNodes()->GetSensitivity(iPoint, 1);
981  if (nDim == 3) {
982  Buffer_Send_Sens_z[nVertex_Surface] = AdjSolver->GetNodes()->GetSensitivity(iPoint, 2);
983  }
984  }
985 
986  /*--- If US system, the output should be in inches ---*/
987 
988  if (config->GetSystemMeasurements() == US) {
989  Buffer_Send_Coord_x[nVertex_Surface] *= 12.0;
990  Buffer_Send_Coord_y[nVertex_Surface] *= 12.0;
991  if (nDim == 3) Buffer_Send_Coord_z[nVertex_Surface] *= 12.0;
992  }
993 
994  nVertex_Surface++;
995  }
996  }
997 
998  su2double *Buffer_Receive_Coord_x = NULL, *Buffer_Receive_Coord_y = NULL, *Buffer_Receive_Coord_z = NULL, *Buffer_Receive_Sensitivity = NULL,
999  *Buffer_Receive_PsiRho = NULL, *Buffer_Receive_Phi_x = NULL, *Buffer_Receive_Phi_y = NULL, *Buffer_Receive_Phi_z = NULL,
1000  *Buffer_Receive_PsiE = NULL, *Buffer_Receive_Sens_x = NULL, *Buffer_Receive_Sens_y = NULL, *Buffer_Receive_Sens_z = NULL;
1001  unsigned long *Buffer_Receive_GlobalPoint = NULL;
1002 
1003  if (rank == MASTER_NODE) {
1004  Buffer_Receive_Coord_x = new su2double [nProcessor*MaxLocalVertex_Surface];
1005  Buffer_Receive_Coord_y = new su2double [nProcessor*MaxLocalVertex_Surface];
1006  if (nDim == 3) Buffer_Receive_Coord_z = new su2double [nProcessor*MaxLocalVertex_Surface];
1007  Buffer_Receive_GlobalPoint = new unsigned long [nProcessor*MaxLocalVertex_Surface];
1008  Buffer_Receive_Sensitivity = new su2double [nProcessor*MaxLocalVertex_Surface];
1009  Buffer_Receive_PsiRho = new su2double [nProcessor*MaxLocalVertex_Surface];
1010  Buffer_Receive_Phi_x = new su2double [nProcessor*MaxLocalVertex_Surface];
1011  Buffer_Receive_Phi_y = new su2double [nProcessor*MaxLocalVertex_Surface];
1012  if (nDim == 3) Buffer_Receive_Phi_z = new su2double [nProcessor*MaxLocalVertex_Surface];
1013  if (config->GetKind_Regime() == COMPRESSIBLE)
1014  Buffer_Receive_PsiE = new su2double [nProcessor*MaxLocalVertex_Surface];
1015  if (config->GetDiscrete_Adjoint()) {
1016  Buffer_Receive_Sens_x = new su2double[nProcessor*MaxLocalVertex_Surface];
1017  Buffer_Receive_Sens_y = new su2double[nProcessor*MaxLocalVertex_Surface];
1018  if (nDim == 3) {
1019  Buffer_Receive_Sens_z = new su2double[nProcessor*MaxLocalVertex_Surface];
1020  }
1021  }
1022  }
1023 
1024  nBuffer_Scalar = MaxLocalVertex_Surface;
1025 
1026  /*--- Send the information to the Master node ---*/
1027  SU2_MPI::Gather(Buffer_Send_Coord_x, nBuffer_Scalar, MPI_DOUBLE, Buffer_Receive_Coord_x, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
1028  SU2_MPI::Gather(Buffer_Send_Coord_y, nBuffer_Scalar, MPI_DOUBLE, Buffer_Receive_Coord_y, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
1029  if (nDim == 3) SU2_MPI::Gather(Buffer_Send_Coord_z, nBuffer_Scalar, MPI_DOUBLE, Buffer_Receive_Coord_z, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
1030  SU2_MPI::Gather(Buffer_Send_GlobalPoint, nBuffer_Scalar, MPI_UNSIGNED_LONG, Buffer_Receive_GlobalPoint, nBuffer_Scalar, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
1031  SU2_MPI::Gather(Buffer_Send_Sensitivity, nBuffer_Scalar, MPI_DOUBLE, Buffer_Receive_Sensitivity, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
1032  SU2_MPI::Gather(Buffer_Send_PsiRho, nBuffer_Scalar, MPI_DOUBLE, Buffer_Receive_PsiRho, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
1033  SU2_MPI::Gather(Buffer_Send_Phi_x, nBuffer_Scalar, MPI_DOUBLE, Buffer_Receive_Phi_x, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
1034  SU2_MPI::Gather(Buffer_Send_Phi_y, nBuffer_Scalar, MPI_DOUBLE, Buffer_Receive_Phi_y, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
1035  if (nDim == 3) SU2_MPI::Gather(Buffer_Send_Phi_z, nBuffer_Scalar, MPI_DOUBLE, Buffer_Receive_Phi_z, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
1036  if (config->GetKind_Regime() == COMPRESSIBLE)
1037  SU2_MPI::Gather(Buffer_Send_PsiE, nBuffer_Scalar, MPI_DOUBLE, Buffer_Receive_PsiE, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
1038  if (config->GetDiscrete_Adjoint()) {
1039  SU2_MPI::Gather(Buffer_Send_Sens_x, nBuffer_Scalar, MPI_DOUBLE, Buffer_Receive_Sens_x, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
1040  SU2_MPI::Gather(Buffer_Send_Sens_y, nBuffer_Scalar, MPI_DOUBLE, Buffer_Receive_Sens_y, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
1041  if (nDim == 3) {
1042  SU2_MPI::Gather(Buffer_Send_Sens_z, nBuffer_Scalar, MPI_DOUBLE, Buffer_Receive_Sens_z, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
1043  }
1044  }
1045 
1046  /*--- The master node is the one who writes the surface files ---*/
1047  if (rank == MASTER_NODE) {
1048  unsigned long iVertex, GlobalPoint, position;
1049  char cstr[200], buffer[50];
1050  ofstream SurfAdj_file;
1051  string filename = config->GetSurfAdjCoeff_FileName();
1052 
1053  /*--- Write file name with extension if unsteady ---*/
1054  strcpy (cstr, filename.c_str());
1055 
1056  if (config->GetTime_Marching() == HARMONIC_BALANCE) {
1057  SPRINTF (buffer, "_%d.csv", SU2_TYPE::Int(val_iInst));
1058 
1059  } else if (config->GetTime_Marching() && config->GetTime_Domain()) {
1060  if ((SU2_TYPE::Int(iExtIter) >= 0) && (SU2_TYPE::Int(iExtIter) < 10)) SPRINTF (buffer, "_0000%d.csv", SU2_TYPE::Int(iExtIter));
1061  if ((SU2_TYPE::Int(iExtIter) >= 10) && (SU2_TYPE::Int(iExtIter) < 100)) SPRINTF (buffer, "_000%d.csv", SU2_TYPE::Int(iExtIter));
1062  if ((SU2_TYPE::Int(iExtIter) >= 100) && (SU2_TYPE::Int(iExtIter) < 1000)) SPRINTF (buffer, "_00%d.csv", SU2_TYPE::Int(iExtIter));
1063  if ((SU2_TYPE::Int(iExtIter) >= 1000) && (SU2_TYPE::Int(iExtIter) < 10000)) SPRINTF (buffer, "_0%d.csv", SU2_TYPE::Int(iExtIter));
1064  if (SU2_TYPE::Int(iExtIter) >= 10000) SPRINTF (buffer, "_%d.csv", SU2_TYPE::Int(iExtIter));
1065  }
1066  else
1067  SPRINTF (buffer, ".csv");
1068 
1069  strcat (cstr, buffer);
1070  SurfAdj_file.open(cstr, ios::out);
1071  SurfAdj_file.precision(15);
1072 
1073  SurfAdj_file << "SENS_AOA=" << AdjSolver->GetTotal_Sens_AoA() * PI_NUMBER / 180.0 << endl;
1074 
1075  /*--- Write the 2D surface flow coefficient file ---*/
1076  if (geometry->GetnDim() == 2) {
1077  if (config->GetKind_Regime() == COMPRESSIBLE)
1078  SurfAdj_file << "\"Point\",\"Sensitivity\",\"PsiRho\",\"Phi_x\",\"Phi_y\",\"PsiE\",\"x_coord\",\"y_coord\"";
1079  else if (config->GetKind_Regime() == INCOMPRESSIBLE)
1080  SurfAdj_file << "\"Point\",\"Sensitivity\",\"PsiRho\",\"Phi_x\",\"Phi_y\",\"x_coord\",\"y_coord\"";
1081 
1082  if (config->GetDiscrete_Adjoint()) {
1083  SurfAdj_file << ",\" x_Sens\",\"y_Sens\"";
1084  }
1085  SurfAdj_file << "\n";
1086 
1087  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++)
1088  for (iVertex = 0; iVertex < Buffer_Receive_nVertex[iProcessor]; iVertex++) {
1089 
1090  position = iProcessor*MaxLocalVertex_Surface+iVertex;
1091  GlobalPoint = Buffer_Receive_GlobalPoint[position];
1092 
1093  if (config->GetKind_Regime() == COMPRESSIBLE)
1094  SurfAdj_file << scientific << GlobalPoint <<
1095  ", " << Buffer_Receive_Sensitivity[position] << ", " << Buffer_Receive_PsiRho[position] <<
1096  ", " << Buffer_Receive_Phi_x[position] << ", " << Buffer_Receive_Phi_y[position] <<
1097  ", " << Buffer_Receive_PsiE[position] << ", " << Buffer_Receive_Coord_x[position] <<
1098  ", "<< Buffer_Receive_Coord_y[position];
1099  else if (config->GetKind_Regime() == INCOMPRESSIBLE)
1100  SurfAdj_file << scientific << GlobalPoint <<
1101  ", " << Buffer_Receive_Sensitivity[position] << ", " << Buffer_Receive_PsiRho[position] <<
1102  ", " << Buffer_Receive_Phi_x[position] << ", " << Buffer_Receive_Phi_y[position] <<
1103  ", " << Buffer_Receive_Coord_x[position] <<
1104  ", "<< Buffer_Receive_Coord_y[position];
1105  if (config->GetDiscrete_Adjoint()) {
1106  SurfAdj_file << ", " << Buffer_Receive_Sens_x[position] << ", " << Buffer_Receive_Sens_y[position];
1107  }
1108  SurfAdj_file << "\n";
1109  }
1110  }
1111 
1112  /*--- Write the 3D surface flow coefficient file ---*/
1113  if (geometry->GetnDim() == 3) {
1114  if (config->GetKind_Regime() == COMPRESSIBLE)
1115  SurfAdj_file << "\"Point\",\"Sensitivity\",\"PsiRho\",\"Phi_x\",\"Phi_y\",\"Phi_z\",\"PsiE\",\"x_coord\",\"y_coord\",\"z_coord\"";
1116  else if (config->GetKind_Regime() == INCOMPRESSIBLE)
1117  SurfAdj_file << "\"Point\",\"Sensitivity\",\"PsiRho\",\"Phi_x\",\"Phi_y\",\"Phi_z\",\"x_coord\",\"y_coord\",\"z_coord\"";
1118 
1119  if (config->GetDiscrete_Adjoint()) {
1120  SurfAdj_file << ",\"x_Sens\",\"y_Sens\",\"z_Sens\"";
1121  }
1122  SurfAdj_file << "\n";
1123 
1124  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++)
1125  for (iVertex = 0; iVertex < Buffer_Receive_nVertex[iProcessor]; iVertex++) {
1126  position = iProcessor*MaxLocalVertex_Surface+iVertex;
1127  GlobalPoint = Buffer_Receive_GlobalPoint[position];
1128 
1129  if (config->GetKind_Regime() == COMPRESSIBLE)
1130  SurfAdj_file << scientific << GlobalPoint <<
1131  ", " << Buffer_Receive_Sensitivity[position] << ", " << Buffer_Receive_PsiRho[position] <<
1132  ", " << Buffer_Receive_Phi_x[position] << ", " << Buffer_Receive_Phi_y[position] << ", " << Buffer_Receive_Phi_z[position] <<
1133  ", " << Buffer_Receive_PsiE[position] <<", "<< Buffer_Receive_Coord_x[position] <<
1134  ", "<< Buffer_Receive_Coord_y[position] <<", "<< Buffer_Receive_Coord_z[position];
1135  else if (config->GetKind_Regime() == INCOMPRESSIBLE)
1136  SurfAdj_file << scientific << GlobalPoint <<
1137  ", " << Buffer_Receive_Sensitivity[position] << ", " << Buffer_Receive_PsiRho[position] <<
1138  ", " << Buffer_Receive_Phi_x[position] << ", " << Buffer_Receive_Phi_y[position] << ", " << Buffer_Receive_Phi_z[position] <<
1139  ", "<< Buffer_Receive_Coord_x[position] <<
1140  ", "<< Buffer_Receive_Coord_y[position] <<", "<< Buffer_Receive_Coord_z[position];
1141 
1142  if (config->GetDiscrete_Adjoint()) {
1143  SurfAdj_file << ", " << Buffer_Receive_Sens_x[position] << ", " << Buffer_Receive_Sens_y[position] << ", " << Buffer_Receive_Sens_z[position];
1144  }
1145  SurfAdj_file << "\n";
1146  }
1147  }
1148 
1149  }
1150 
1151  if (rank == MASTER_NODE) {
1152  delete [] Buffer_Receive_nVertex;
1153  delete [] Buffer_Receive_Coord_x;
1154  delete [] Buffer_Receive_Coord_y;
1155  if (nDim == 3) delete [] Buffer_Receive_Coord_z;
1156  delete [] Buffer_Receive_Sensitivity;
1157  delete [] Buffer_Receive_PsiRho;
1158  delete [] Buffer_Receive_Phi_x;
1159  delete [] Buffer_Receive_Phi_y;
1160  if (nDim == 3) delete [] Buffer_Receive_Phi_z;
1161  if (config->GetKind_Regime() == COMPRESSIBLE)
1162  delete [] Buffer_Receive_PsiE;
1163  delete [] Buffer_Receive_GlobalPoint;
1164  if (config->GetDiscrete_Adjoint()) {
1165  delete [] Buffer_Receive_Sens_x;
1166  delete [] Buffer_Receive_Sens_y;
1167  if (nDim == 3) {
1168  delete [] Buffer_Receive_Sens_z;
1169  }
1170  }
1171  }
1172 
1173  delete [] Buffer_Send_Coord_x;
1174  delete [] Buffer_Send_Coord_y;
1175  delete [] Buffer_Send_Coord_z;
1176  delete [] Buffer_Send_GlobalPoint;
1177  delete [] Buffer_Send_Sensitivity;
1178  delete [] Buffer_Send_PsiRho;
1179  delete [] Buffer_Send_Phi_x;
1180  delete [] Buffer_Send_Phi_y;
1181  delete [] Buffer_Send_Phi_z;
1182  delete [] Buffer_Send_PsiE;
1183  if (Buffer_Send_Sens_x != NULL) delete [] Buffer_Send_Sens_x;
1184  if (Buffer_Send_Sens_y != NULL) delete [] Buffer_Send_Sens_y;
1185  if (Buffer_Send_Sens_z != NULL) delete [] Buffer_Send_Sens_z;
1186 
1187  SurfAdj_file.close();
1188 
1189 #endif
1190 }
1191 
1192 void COutputLegacy::MergeConnectivity(CConfig *config, CGeometry *geometry, unsigned short val_iZone) {
1193 
1194  /*--- Flags identifying the types of files to be written. ---*/
1195 
1196  bool Wrt_Vol = config->GetWrt_Vol_Sol();
1197  bool Wrt_Srf = config->GetWrt_Srf_Sol();
1198 
1199  /*--- Merge connectivity for each type of element (excluding halos). Note
1200  that we only need to merge the connectivity once, as it does not change
1201  during computation. Check whether the base file has been written. ---*/
1202 
1203  /*--- Merge volumetric grid. ---*/
1204 
1205  if (Wrt_Vol) {
1206 
1207  if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_Tria != 0))
1208  cout <<"Merging volumetric triangle grid connectivity." << endl;
1209  MergeVolumetricConnectivity(config, geometry, TRIANGLE );
1210 
1211  if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_Quad != 0))
1212  cout <<"Merging volumetric quadrilateral grid connectivity." << endl;
1213  MergeVolumetricConnectivity(config, geometry, QUADRILATERAL );
1214 
1215  if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_Tetr != 0))
1216  cout <<"Merging volumetric tetrahedron grid connectivity." << endl;
1217  MergeVolumetricConnectivity(config, geometry, TETRAHEDRON );
1218 
1219  if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_Hexa != 0))
1220  cout <<"Merging volumetric hexahedron grid connectivity." << endl;
1221  MergeVolumetricConnectivity(config, geometry, HEXAHEDRON );
1222 
1223  if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_Pris != 0))
1224  cout <<"Merging volumetric prism grid connectivity." << endl;
1225  MergeVolumetricConnectivity(config, geometry, PRISM );
1226 
1227  if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_Pyra != 0))
1228  cout <<"Merging volumetric pyramid grid connectivity." << endl;
1229  MergeVolumetricConnectivity(config, geometry, PYRAMID );
1230 
1231  }
1232 
1233  /*--- Merge surface grid. ---*/
1234 
1235  if (Wrt_Srf) {
1236 
1237  if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_Line != 0))
1238  cout <<"Merging surface line grid connectivity." << endl;
1239  MergeSurfaceConnectivity(config, geometry, LINE);
1240 
1241  if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_BoundTria != 0))
1242  cout <<"Merging surface triangle grid connectivity." << endl;
1243  MergeSurfaceConnectivity(config, geometry, TRIANGLE);
1244 
1245  if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_BoundQuad != 0))
1246  cout <<"Merging surface quadrilateral grid connectivity." << endl;
1247  MergeSurfaceConnectivity(config, geometry, QUADRILATERAL);
1248 
1249  }
1250 
1251  /*--- Update total number of volume elements after merge. ---*/
1252 
1253  nGlobal_Elem = nGlobal_Tria + nGlobal_Quad + nGlobal_Tetr +
1254  nGlobal_Hexa + nGlobal_Pyra + nGlobal_Pris;
1255 
1256  /*--- Update total number of surface elements after merge. ---*/
1257 
1258  nSurf_Elem = nGlobal_Line + nGlobal_BoundTria + nGlobal_BoundQuad;
1259 
1260 }
1261 
1263 
1264  /*--- Local variables needed on all processors ---*/
1265 
1266  unsigned short iDim, nDim = geometry->GetnDim();
1267  unsigned long iPoint;
1268 
1269  unsigned short kind_SU2 = config->GetKind_SU2();
1270 
1271 #ifndef HAVE_MPI
1272 
1273  /*--- In serial, the single process has access to all geometry, so simply
1274  load the coordinates into the data structure. ---*/
1275 
1276  unsigned short iMarker;
1277  unsigned long iVertex, nTotalPoints = 0;
1278  int SendRecv;
1279 
1280  bool isPeriodic;
1281 
1282  /*--- First, create a structure to locate any periodic halo nodes ---*/
1283  int *Local_Halo = new int[geometry->GetnPoint()];
1284  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
1285  Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain();
1286 
1287  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
1288  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
1289  SendRecv = config->GetMarker_All_SendRecv(iMarker);
1290  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
1291  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
1292 
1293  /*--- For SU2_CFD and SU2_SOL we want to remove the periodic halo nodes,
1294  * but for SU2_DEF we want them to be included, therefore the definition of a periodic point
1295  * is different in each case ---*/
1296 
1297  if (kind_SU2 == SU2_DEF) {
1298  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0));
1299  }else {
1300  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
1301  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1));
1302  }
1303 
1304  if (isPeriodic && (SendRecv < 0)) {
1305  Local_Halo[iPoint] = false;
1306  }
1307  }
1308 
1309  }
1310  }
1311 
1312  /*--- Total number of points in the mesh (this might include periodic points). ---*/
1313  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
1314  if (!Local_Halo[iPoint]) nTotalPoints++;
1315 
1316  nGlobal_Poin = nTotalPoints;
1317  nGlobal_Doma = geometry->GetnPointDomain();
1318 
1319  /*--- Allocate the coordinates data structure. ---*/
1320 
1321  Coords = new su2double*[nDim];
1322  for (iDim = 0; iDim < nDim; iDim++) {
1323  Coords[iDim] = new su2double[nGlobal_Poin];
1324  }
1325 
1326  /*--- Loop over the mesh to collect the coords of the local points ---*/
1327 
1328  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
1329 
1330  /*--- Check if the node belongs to the domain (i.e, not a halo node).
1331  Sort by the global index, even in serial there is a renumbering (e.g. RCM). ---*/
1332 
1333  if (!Local_Halo[iPoint]) {
1334 
1335  /*--- Retrieve the current coordinates at this node. ---*/
1336 
1337  unsigned long iGlobal_Index = geometry->node[iPoint]->GetGlobalIndex();
1338 
1339  for (iDim = 0; iDim < nDim; iDim++) {
1340  Coords[iDim][iGlobal_Index] = geometry->node[iPoint]->GetCoord(iDim);
1341 
1342  /*--- If US system, the output should be in inches ---*/
1343 
1344  if ((config->GetSystemMeasurements() == US) && (config->GetKind_SU2() != SU2_DEF)) {
1345  Coords[iDim][iGlobal_Index] *= 12.0;
1346  }
1347 
1348  }
1349 
1350  }
1351  }
1352 
1353 
1354  delete [] Local_Halo;
1355 
1356 #else
1357 
1358  /*--- MPI preprocessing ---*/
1359  int iProcessor, nProcessor = size;
1360  unsigned long jPoint;
1361 
1362  bool Wrt_Halo = config->GetWrt_Halo(), isPeriodic;
1363 
1364  /*--- Local variables needed for merging the geometry with MPI. ---*/
1365 
1366  unsigned long iVertex, iMarker;
1367  unsigned long Buffer_Send_nPoin[1], *Buffer_Recv_nPoin = NULL;
1368  unsigned long nLocalPoint = 0, MaxLocalPoint = 0;
1369  unsigned long iGlobal_Index = 0, nBuffer_Scalar = 0;
1370 
1371  if (rank == MASTER_NODE) Buffer_Recv_nPoin = new unsigned long[nProcessor];
1372 
1373  int *Local_Halo = new int[geometry->GetnPoint()];
1374  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
1375  Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain();
1376 
1377  /*--- Search all send/recv boundaries on this partition for any periodic
1378  nodes that were part of the original domain. We want to recover these
1379  for visualization purposes. ---*/
1380 
1381  if (Wrt_Halo) {
1382  nLocalPoint = geometry->GetnPoint();
1383  } else {
1384  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
1385  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
1386 
1387  /*--- Checking for less than or equal to the rank, because there may
1388  be some periodic halo nodes that send info to the same rank. ---*/
1389 
1390  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
1391  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
1392 
1393  /*--- For SU2_CFD and SU2_SOL we want to remove the periodic halo nodes,
1394  * but for SU2_DEF we want them to be included, therefore the definition of a periodic point
1395  * is different in each case ---*/
1396 
1397  if (kind_SU2 == SU2_DEF) {
1398  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0));
1399  }else {
1400  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
1401  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1));
1402  }
1403  if (isPeriodic) {
1404  Local_Halo[iPoint] = false;
1405  }
1406  }
1407  }
1408  }
1409 
1410  /*--- Sum total number of nodes that belong to the domain ---*/
1411 
1412  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
1413  if (Local_Halo[iPoint] == false)
1414  nLocalPoint++;
1415  }
1416  Buffer_Send_nPoin[0] = nLocalPoint;
1417 
1418  /*--- Communicate the total number of nodes on this domain. ---*/
1419 
1420  SU2_MPI::Gather(&Buffer_Send_nPoin, 1, MPI_UNSIGNED_LONG,
1421  Buffer_Recv_nPoin, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
1422  SU2_MPI::Allreduce(&nLocalPoint, &MaxLocalPoint, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
1423 
1424  if (rank == MASTER_NODE) {
1425  nGlobal_Doma = 0;
1426  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
1427  nGlobal_Doma += Buffer_Recv_nPoin[iProcessor];
1428  }
1429  }
1430  nBuffer_Scalar = MaxLocalPoint;
1431 
1432  /*--- Send and Recv buffers. ---*/
1433 
1434  su2double *Buffer_Send_X = new su2double[MaxLocalPoint];
1435  su2double *Buffer_Recv_X = NULL;
1436 
1437  su2double *Buffer_Send_Y = new su2double[MaxLocalPoint];
1438  su2double *Buffer_Recv_Y = NULL;
1439 
1440  su2double *Buffer_Send_Z = NULL, *Buffer_Recv_Z = NULL;
1441  if (nDim == 3) Buffer_Send_Z = new su2double[MaxLocalPoint];
1442 
1443  unsigned long *Buffer_Send_GlobalIndex = new unsigned long[MaxLocalPoint];
1444  unsigned long *Buffer_Recv_GlobalIndex = NULL;
1445 
1446  /*--- Prepare the receive buffers in the master node only. ---*/
1447 
1448  if (rank == MASTER_NODE) {
1449 
1450  Buffer_Recv_X = new su2double[nProcessor*MaxLocalPoint];
1451  Buffer_Recv_Y = new su2double[nProcessor*MaxLocalPoint];
1452  if (nDim == 3) Buffer_Recv_Z = new su2double[nProcessor*MaxLocalPoint];
1453  Buffer_Recv_GlobalIndex = new unsigned long[nProcessor*MaxLocalPoint];
1454 
1455  /*--- Sum total number of nodes to be written and allocate arrays ---*/
1456  nGlobal_Poin = 0;
1457  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
1458  nGlobal_Poin += Buffer_Recv_nPoin[iProcessor];
1459  }
1460  Coords = new su2double*[nDim];
1461  for (iDim = 0; iDim < nDim; iDim++) {
1462  Coords[iDim] = new su2double[nGlobal_Poin];
1463  }
1464  }
1465 
1466  /*--- Main communication routine. Loop over each coordinate and perform
1467  the MPI comm. Temporary 1-D buffers are used to send the coordinates at
1468  all nodes on each partition to the master node. These are then unpacked
1469  by the master and sorted by global index in one large n-dim. array. ---*/
1470 
1471  /*--- Loop over this partition to collect the coords of the local points. ---*/
1472  su2double *Coords_Local; jPoint = 0;
1473  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
1474 
1475  /*--- Check for halos and write only if requested ---*/
1476  if (!Local_Halo[iPoint] || Wrt_Halo) {
1477 
1478  /*--- Retrieve local coordinates at this node. ---*/
1479  Coords_Local = geometry->node[iPoint]->GetCoord();
1480 
1481  /*--- Load local coords into the temporary send buffer. ---*/
1482  Buffer_Send_X[jPoint] = Coords_Local[0];
1483  Buffer_Send_Y[jPoint] = Coords_Local[1];
1484  if (nDim == 3) Buffer_Send_Z[jPoint] = Coords_Local[2];
1485 
1486  /*--- If US system, the output should be in inches ---*/
1487 
1488  if ((config->GetSystemMeasurements() == US) && (config->GetKind_SU2() != SU2_DEF)) {
1489  Buffer_Send_X[jPoint] *= 12.0;
1490  Buffer_Send_Y[jPoint] *= 12.0;
1491  if (nDim == 3) Buffer_Send_Z[jPoint] *= 12.0;
1492  }
1493 
1494  /*--- Store the global index for this local node. ---*/
1495  Buffer_Send_GlobalIndex[jPoint] = geometry->node[iPoint]->GetGlobalIndex();
1496 
1497  /*--- Increment jPoint as the counter. We need this because iPoint
1498  may include halo nodes that we skip over during this loop. ---*/
1499  jPoint++;
1500  }
1501  }
1502 
1503  /*--- Gather the coordinate data on the master node using MPI. ---*/
1504 
1505  SU2_MPI::Gather(Buffer_Send_X, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_X, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
1506  SU2_MPI::Gather(Buffer_Send_Y, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Y, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
1507  if (nDim == 3) {
1508  SU2_MPI::Gather(Buffer_Send_Z, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Z, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
1509  }
1510  SU2_MPI::Gather(Buffer_Send_GlobalIndex, nBuffer_Scalar, MPI_UNSIGNED_LONG, Buffer_Recv_GlobalIndex, nBuffer_Scalar, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
1511 
1512  /*--- The master node unpacks and sorts this variable by global index ---*/
1513 
1514  if (rank == MASTER_NODE) {
1515  jPoint = 0;
1516  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
1517  for (iPoint = 0; iPoint < Buffer_Recv_nPoin[iProcessor]; iPoint++) {
1518  /*--- Get global index, then loop over each variable and store ---*/
1519  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
1520  if (iGlobal_Index >= nGlobal_Poin) {
1521  cout << iGlobal_Index << " " << nGlobal_Poin << endl;
1522  }
1523  Coords[0][iGlobal_Index] = Buffer_Recv_X[jPoint];
1524  Coords[1][iGlobal_Index] = Buffer_Recv_Y[jPoint];
1525  if (nDim == 3) Coords[2][iGlobal_Index] = Buffer_Recv_Z[jPoint];
1526  jPoint++;
1527  }
1528  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
1529  jPoint = (iProcessor+1)*nBuffer_Scalar;
1530  }
1531  }
1532 
1533  /*--- Immediately release the temporary data buffers. ---*/
1534 
1535  delete [] Local_Halo;
1536  delete [] Buffer_Send_X;
1537  delete [] Buffer_Send_Y;
1538  if (Buffer_Send_Z != NULL) delete [] Buffer_Send_Z;
1539  delete [] Buffer_Send_GlobalIndex;
1540  if (rank == MASTER_NODE) {
1541  delete [] Buffer_Recv_X;
1542  delete [] Buffer_Recv_Y;
1543  if (Buffer_Recv_Z != NULL) delete [] Buffer_Recv_Z;
1544  delete [] Buffer_Recv_GlobalIndex;
1545  delete [] Buffer_Recv_nPoin;
1546  }
1547 
1548 #endif
1549 
1550 }
1551 
1552 void COutputLegacy::MergeVolumetricConnectivity(CConfig *config, CGeometry *geometry, unsigned short Elem_Type) {
1553 
1554  int iProcessor;
1555  unsigned short NODES_PER_ELEMENT = 0;
1556  unsigned long iPoint, iNode, jNode;
1557  unsigned long iElem = 0;
1558  unsigned long nLocalElem = 0, nElem_Total = 0;
1559 
1560  unsigned long iVertex, iMarker;
1561  unsigned long jElem;
1562  int SendRecv, RecvFrom;
1563 
1564  unsigned long Buffer_Send_nElem[1], *Buffer_Recv_nElem = NULL;
1565  unsigned long nBuffer_Scalar = 0;
1566  unsigned long kNode = 0, kElem = 0;
1567  unsigned long MaxLocalElem = 0, iGlobal_Index, jPoint, kPoint;
1568 
1569  bool Wrt_Halo = config->GetWrt_Halo();
1570  bool *Write_Elem = NULL, notPeriodic, notHalo, addedPeriodic, isPeriodic;
1571 
1572  unsigned short kind_SU2 = config->GetKind_SU2();
1573 
1574  int *Conn_Elem = NULL;
1575 
1576  /*--- Store the local number of this element type and the number of nodes
1577  per this element type. In serial, this will be the total number of this
1578  element type in the entire mesh. In parallel, it is the number on only
1579  the current partition. ---*/
1580 
1581  switch (Elem_Type) {
1582  case TRIANGLE:
1583  nLocalElem = geometry->GetnElemTria();
1584  NODES_PER_ELEMENT = N_POINTS_TRIANGLE;
1585  break;
1586  case QUADRILATERAL:
1587  nLocalElem = geometry->GetnElemQuad();
1588  NODES_PER_ELEMENT = N_POINTS_QUADRILATERAL;
1589  break;
1590  case TETRAHEDRON:
1591  nLocalElem = geometry->GetnElemTetr();
1592  NODES_PER_ELEMENT = N_POINTS_TETRAHEDRON;
1593  break;
1594  case HEXAHEDRON:
1595  nLocalElem = geometry->GetnElemHexa();
1596  NODES_PER_ELEMENT = N_POINTS_HEXAHEDRON;
1597  break;
1598  case PRISM:
1599  nLocalElem = geometry->GetnElemPris();
1600  NODES_PER_ELEMENT = N_POINTS_PRISM;
1601  break;
1602  case PYRAMID:
1603  nLocalElem = geometry->GetnElemPyra();
1604  NODES_PER_ELEMENT = N_POINTS_PYRAMID;
1605  break;
1606  default:
1607  SU2_MPI::Error("Unrecognized element type", CURRENT_FUNCTION);
1608  }
1609 
1610  /*--- Find the max number of this element type among all
1611  partitions and set up buffers. ---*/
1612 
1613  Buffer_Send_nElem[0] = nLocalElem;
1614  if (rank == MASTER_NODE) Buffer_Recv_nElem = new unsigned long[size];
1615 
1616 #ifdef HAVE_MPI
1617  SU2_MPI::Allreduce(&nLocalElem, &MaxLocalElem, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
1618  SU2_MPI::Gather(&Buffer_Send_nElem, 1, MPI_UNSIGNED_LONG, Buffer_Recv_nElem, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
1619 #else
1620  MaxLocalElem = nLocalElem;
1621  Buffer_Recv_nElem[0] = Buffer_Send_nElem[0];
1622 #endif
1623 
1624  nBuffer_Scalar = MaxLocalElem*NODES_PER_ELEMENT;
1625 
1626  /*--- Send and Recv buffers ---*/
1627 
1628  unsigned long *Buffer_Send_Elem = new unsigned long[nBuffer_Scalar];
1629  unsigned long *Buffer_Recv_Elem = NULL;
1630 
1631  unsigned short *Buffer_Send_Halo = new unsigned short[MaxLocalElem];
1632  unsigned short *Buffer_Recv_Halo = NULL;
1633 
1634  /*--- Prepare the receive buffers on the master node only. ---*/
1635 
1636  if (rank == MASTER_NODE) {
1637  Buffer_Recv_Elem = new unsigned long[size*nBuffer_Scalar];
1638  Buffer_Recv_Halo = new unsigned short[size*MaxLocalElem];
1639  if (MaxLocalElem > 0) Conn_Elem = new int[size*MaxLocalElem*NODES_PER_ELEMENT];
1640  }
1641 
1642  /*--- Force the removal of all added periodic elements (use global index).
1643  First, we isolate and create a list of all added periodic points, excluding
1644  those that we part of the original domain (we want these to be in the
1645  output files). ---*/
1646 
1647  vector<unsigned long> Added_Periodic;
1648  Added_Periodic.clear();
1649 
1650  if (kind_SU2 != SU2_DEF) {
1651  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
1652  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
1653  SendRecv = config->GetMarker_All_SendRecv(iMarker);
1654  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
1655  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
1656 
1657  if ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
1658  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 0) &&
1659  (SendRecv < 0)) {
1660  Added_Periodic.push_back(geometry->node[iPoint]->GetGlobalIndex());
1661  }
1662  }
1663  }
1664  }
1665  }
1666 
1667  /*--- Now we communicate this information to all processors, so that they
1668  can force the removal of these particular nodes by flagging them as halo
1669  points. In general, this should be a small percentage of the total mesh,
1670  so the communication/storage costs here shouldn't be prohibitive. ---*/
1671 
1672  /*--- First communicate the number of points that each rank has found ---*/
1673  unsigned long nAddedPeriodic = 0, maxAddedPeriodic = 0;
1674  unsigned long Buffer_Send_nAddedPeriodic[1], *Buffer_Recv_nAddedPeriodic = NULL;
1675  Buffer_Recv_nAddedPeriodic = new unsigned long[size];
1676 
1677  nAddedPeriodic = Added_Periodic.size();
1678  Buffer_Send_nAddedPeriodic[0] = nAddedPeriodic;
1679 
1680 #ifdef HAVE_MPI
1681  SU2_MPI::Allreduce(&nAddedPeriodic, &maxAddedPeriodic, 1, MPI_UNSIGNED_LONG,
1683  SU2_MPI::Allgather(&Buffer_Send_nAddedPeriodic, 1, MPI_UNSIGNED_LONG,
1684  Buffer_Recv_nAddedPeriodic, 1, MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
1685 #else
1686  maxAddedPeriodic = nAddedPeriodic;
1687  Buffer_Recv_nAddedPeriodic[0] = Buffer_Send_nAddedPeriodic[0];
1688 #endif
1689 
1690  /*--- Communicate the global index values of all added periodic nodes. ---*/
1691  unsigned long *Buffer_Send_AddedPeriodic = new unsigned long[maxAddedPeriodic];
1692  unsigned long *Buffer_Recv_AddedPeriodic = new unsigned long[size*maxAddedPeriodic];
1693 
1694  for (iPoint = 0; iPoint < Added_Periodic.size(); iPoint++) {
1695  Buffer_Send_AddedPeriodic[iPoint] = Added_Periodic[iPoint];
1696  }
1697 
1698  /*--- Gather the element connectivity information. All processors will now
1699  have a copy of the global index values for all added periodic points. ---*/
1700 
1701 #ifdef HAVE_MPI
1702  SU2_MPI::Allgather(Buffer_Send_AddedPeriodic, maxAddedPeriodic, MPI_UNSIGNED_LONG,
1703  Buffer_Recv_AddedPeriodic, maxAddedPeriodic, MPI_UNSIGNED_LONG,
1704  MPI_COMM_WORLD);
1705 #else
1706  for (iPoint = 0; iPoint < maxAddedPeriodic; iPoint++) Buffer_Recv_AddedPeriodic[iPoint] = Buffer_Send_AddedPeriodic[iPoint];
1707 #endif
1708 
1709  /*--- Search all send/recv boundaries on this partition for halo cells. In
1710  particular, consider only the recv conditions (these are the true halo
1711  nodes). Check the ranks of the processors that are communicating and
1712  choose to keep only the halo cells from the higher rank processor. Here,
1713  we are also choosing to keep periodic nodes that were part of the original
1714  domain. We will check the communicated list of added periodic points. ---*/
1715 
1716  int *Local_Halo = new int[geometry->GetnPoint()];
1717  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
1718  Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain();
1719 
1720  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
1721  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
1722  SendRecv = config->GetMarker_All_SendRecv(iMarker);
1723  RecvFrom = abs(SendRecv)-1;
1724 
1725  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
1726  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
1727  iGlobal_Index = geometry->node[iPoint]->GetGlobalIndex();
1728 
1729  /*--- We need to keep one copy of overlapping halo cells. ---*/
1730  notHalo = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() == 0) &&
1731  (SendRecv < 0) && (rank > RecvFrom));
1732 
1733  /*--- We want to keep the periodic nodes that were part of the original domain.
1734  For SU2_DEF we want to keep all periodic nodes. ---*/
1735 
1736  if (kind_SU2 == SU2_DEF) {
1737  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0));
1738  }else {
1739  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
1740  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1));
1741  }
1742 
1743  notPeriodic = (isPeriodic && (SendRecv < 0));
1744 
1745  /*--- Lastly, check that this isn't an added periodic point that
1746  we will forcibly remove. Use the communicated list of these points. ---*/
1747  addedPeriodic = false; kPoint = 0;
1748  for (iProcessor = 0; iProcessor < size; iProcessor++) {
1749  for (jPoint = 0; jPoint < Buffer_Recv_nAddedPeriodic[iProcessor]; jPoint++) {
1750  if (iGlobal_Index == Buffer_Recv_AddedPeriodic[kPoint+jPoint])
1751  addedPeriodic = true;
1752  }
1753  /*--- Adjust jNode to index of next proc's data in the buffers. ---*/
1754  kPoint = (iProcessor+1)*maxAddedPeriodic;
1755  }
1756 
1757  /*--- If we found either of these types of nodes, flag them to be kept. ---*/
1758  if ((notHalo || notPeriodic) && !addedPeriodic) {
1759  Local_Halo[iPoint] = false;
1760  }
1761  }
1762  }
1763  }
1764 
1765  /*--- Loop over all elements in this partition and load the
1766  elements of the current type into the buffer to be sent to
1767  the master node. ---*/
1768 
1769  jNode = 0; jElem = 0;
1770  for (iElem = 0; iElem < geometry->GetnElem(); iElem++) {
1771  if (geometry->elem[iElem]->GetVTK_Type() == Elem_Type) {
1772 
1773  /*--- Loop over all nodes in this element and load the
1774  connectivity into the send buffer. ---*/
1775 
1776  Buffer_Send_Halo[jElem] = false;
1777  for (iNode = 0; iNode < NODES_PER_ELEMENT; iNode++) {
1778 
1779  /*--- Store the global index values directly. ---*/
1780 
1781  iPoint = geometry->elem[iElem]->GetNode(iNode);
1782  Buffer_Send_Elem[jNode] = geometry->node[iPoint]->GetGlobalIndex();
1783 
1784  /*--- Check if this is a halo node. If so, flag this element
1785  as a halo cell. We will use this later to sort and remove
1786  any duplicates from the connectivity list. ---*/
1787 
1788  if (Local_Halo[iPoint]) {
1789  Buffer_Send_Halo[jElem] = true;
1790  }
1791 
1792  /*--- Increment jNode as the counter. We need this because iElem
1793  may include other elements that we skip over during this loop. ---*/
1794 
1795  jNode++;
1796  }
1797  jElem++;
1798  }
1799  }
1800 
1801  /*--- Gather the element connectivity information. ---*/
1802 
1803 #ifdef HAVE_MPI
1804  SU2_MPI::Gather(Buffer_Send_Elem, nBuffer_Scalar, MPI_UNSIGNED_LONG, Buffer_Recv_Elem, nBuffer_Scalar, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
1805  SU2_MPI::Gather(Buffer_Send_Halo, MaxLocalElem, MPI_UNSIGNED_SHORT, Buffer_Recv_Halo, MaxLocalElem, MPI_UNSIGNED_SHORT, MASTER_NODE, MPI_COMM_WORLD);
1806 #else
1807  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Elem[iPoint] = Buffer_Send_Elem[iPoint];
1808  for (iPoint = 0; iPoint < MaxLocalElem; iPoint++) Buffer_Recv_Halo[iPoint] = Buffer_Send_Halo[iPoint];
1809 #endif
1810 
1811  /*--- The master node unpacks and sorts the connectivity. ---*/
1812 
1813  if (rank == MASTER_NODE) {
1814 
1815  /*--- We need to remove any duplicate elements (halo cells) that
1816  exist on multiple partitions. Start by initializing all elements
1817  to the "write" state by using a boolean array. ---*/
1818 
1819  Write_Elem = new bool[size*MaxLocalElem];
1820  for (iElem = 0; iElem < size*MaxLocalElem; iElem++) {
1821  Write_Elem[iElem] = true;
1822  }
1823 
1824  /*--- Remove the rind layer from the solution only if requested ---*/
1825 
1826  if (!Wrt_Halo) {
1827 
1828  /*--- Loop for flagging duplicate elements so that they are not
1829  included in the final connectivity list. ---*/
1830 
1831  kElem = 0;
1832  for (iProcessor = 0; iProcessor < size; iProcessor++) {
1833  for (iElem = 0; iElem < Buffer_Recv_nElem[iProcessor]; iElem++) {
1834 
1835  /*--- Check if this element was marked as a halo. ---*/
1836  if (Buffer_Recv_Halo[kElem+iElem])
1837  Write_Elem[kElem+iElem] = false;
1838 
1839  }
1840  kElem = (iProcessor+1)*MaxLocalElem;
1841  }
1842  }
1843 
1844  /*--- Store the unique connectivity list for this element type. ---*/
1845 
1846  jNode = 0; kNode = 0; jElem = 0; nElem_Total = 0;
1847  for (iProcessor = 0; iProcessor < size; iProcessor++) {
1848  for (iElem = 0; iElem < Buffer_Recv_nElem[iProcessor]; iElem++) {
1849 
1850  /*--- Only write the elements that were flagged for it. ---*/
1851  if (Write_Elem[jElem+iElem]) {
1852 
1853  /*--- Increment total count for this element type ---*/
1854  nElem_Total++;
1855 
1856  /*--- Get global index, then loop over each variable and store.
1857  Note that we are adding one to the index value because CGNS/Tecplot
1858  use 1-based indexing.---*/
1859 
1860  for (iNode = 0; iNode < NODES_PER_ELEMENT; iNode++) {
1861  Conn_Elem[kNode] = (int)Buffer_Recv_Elem[jNode+iElem*NODES_PER_ELEMENT+iNode] + 1;
1862  kNode++;
1863  }
1864  }
1865  }
1866  /*--- Adjust jNode to index of next proc's data in the buffers. ---*/
1867  jElem = (iProcessor+1)*MaxLocalElem;
1868  jNode = (iProcessor+1)*nBuffer_Scalar;
1869  }
1870  }
1871 
1872  /*--- Immediately release the temporary buffers. ---*/
1873  delete [] Buffer_Send_Elem;
1874  delete [] Buffer_Send_Halo;
1875  delete [] Buffer_Recv_nAddedPeriodic;
1876  delete [] Buffer_Send_AddedPeriodic;
1877  delete [] Buffer_Recv_AddedPeriodic;
1878  delete [] Local_Halo;
1879  if (rank == MASTER_NODE) {
1880  delete [] Buffer_Recv_nElem;
1881  delete [] Buffer_Recv_Elem;
1882  delete [] Buffer_Recv_Halo;
1883  delete [] Write_Elem;
1884  }
1885 
1886  /*--- Store the particular global element count in the class data,
1887  and set the class data pointer to the connectivity array. ---*/
1888 
1889  if (rank == MASTER_NODE) {
1890  switch (Elem_Type) {
1891  case TRIANGLE:
1892  nGlobal_Tria = nElem_Total;
1893  if (nGlobal_Tria > 0) Conn_Tria = Conn_Elem;
1894  break;
1895  case QUADRILATERAL:
1896  nGlobal_Quad = nElem_Total;
1897  if (nGlobal_Quad > 0) Conn_Quad = Conn_Elem;
1898  break;
1899  case TETRAHEDRON:
1900  nGlobal_Tetr = nElem_Total;
1901  if (nGlobal_Tetr > 0) Conn_Tetr = Conn_Elem;
1902  break;
1903  case HEXAHEDRON:
1904  nGlobal_Hexa = nElem_Total;
1905  if (nGlobal_Hexa > 0) Conn_Hexa = Conn_Elem;
1906  break;
1907  case PRISM:
1908  nGlobal_Pris = nElem_Total;
1909  if (nGlobal_Pris > 0) Conn_Pris = Conn_Elem;
1910  break;
1911  case PYRAMID:
1912  nGlobal_Pyra = nElem_Total;
1913  if (nGlobal_Pyra > 0) Conn_Pyra = Conn_Elem;
1914  break;
1915  default:
1916  SU2_MPI::Error("Unrecognized element type", CURRENT_FUNCTION);
1917  break;
1918  }
1919  }
1920 
1921 }
1922 
1923 void COutputLegacy::MergeSurfaceConnectivity(CConfig *config, CGeometry *geometry, unsigned short Elem_Type) {
1924 
1925  unsigned short NODES_PER_ELEMENT;
1926 
1927  unsigned short iMarker;
1928  unsigned long iPoint, iNode, jNode;
1929  unsigned long iElem = 0;
1930  unsigned long nLocalElem = 0, nElem_Total = 0;
1931 
1932  int iProcessor;
1933  unsigned long jElem;
1934 
1935  unsigned long iVertex;
1936 
1937  int SendRecv, RecvFrom;
1938 
1939  unsigned long Buffer_Send_nElem[1], *Buffer_Recv_nElem = NULL;
1940  unsigned long nBuffer_Scalar = 0;
1941  unsigned long kNode = 0, kElem = 0;
1942  unsigned long MaxLocalElem = 0, iGlobal_Index, jPoint, kPoint;
1943 
1944  bool Wrt_Halo = config->GetWrt_Halo();
1945  bool *Write_Elem = NULL, notPeriodic, notHalo, addedPeriodic;
1946 
1947 
1948  int *Conn_Elem = NULL;
1949 
1950  /*--- Store the local number of this element type and the number of nodes
1951  per this element type. In serial, this will be the total number of this
1952  element type in the entire mesh. In parallel, it is the number on only
1953  the current partition. ---*/
1954 
1955  nLocalElem = 0;
1956 
1957  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
1958  if (config->GetMarker_All_Plotting(iMarker) == YES) {
1959  for (iElem = 0; iElem < geometry->GetnElem_Bound(iMarker); iElem++) {
1960  if (geometry->bound[iMarker][iElem]->GetVTK_Type() == Elem_Type) {
1961  nLocalElem++;
1962  }
1963  }
1964  }
1965  }
1966 
1967  switch (Elem_Type) {
1968  case LINE:
1969  NODES_PER_ELEMENT = N_POINTS_LINE;
1970  break;
1971  case TRIANGLE:
1972  NODES_PER_ELEMENT = N_POINTS_TRIANGLE;
1973  break;
1974  case QUADRILATERAL:
1975  NODES_PER_ELEMENT = N_POINTS_QUADRILATERAL;
1976  break;
1977  default:
1978  SU2_MPI::Error("Unrecognized element type", CURRENT_FUNCTION);
1979  NODES_PER_ELEMENT = 0;
1980  break;
1981  }
1982 
1983  /*--- Find the max number of this element type among all
1984  partitions and set up buffers. ---*/
1985 
1986  Buffer_Send_nElem[0] = nLocalElem;
1987  if (rank == MASTER_NODE) Buffer_Recv_nElem = new unsigned long[size];
1988 
1989 #ifdef HAVE_MPI
1990  SU2_MPI::Allreduce(&nLocalElem, &MaxLocalElem, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
1991  SU2_MPI::Gather(&Buffer_Send_nElem, 1, MPI_UNSIGNED_LONG, Buffer_Recv_nElem, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
1992 #else
1993  MaxLocalElem = nLocalElem;
1994  Buffer_Recv_nElem[0] = Buffer_Send_nElem[0];
1995 #endif
1996 
1997  nBuffer_Scalar = MaxLocalElem*NODES_PER_ELEMENT;
1998 
1999  /*--- Send and Recv buffers ---*/
2000 
2001  unsigned long *Buffer_Send_Elem = new unsigned long[nBuffer_Scalar];
2002  unsigned long *Buffer_Recv_Elem = NULL;
2003 
2004  unsigned short *Buffer_Send_Halo = new unsigned short[MaxLocalElem];
2005  unsigned short *Buffer_Recv_Halo = NULL;
2006 
2007  /*--- Prepare the receive buffers on the master node only. ---*/
2008 
2009  if (rank == MASTER_NODE) {
2010  Buffer_Recv_Elem = new unsigned long[size*nBuffer_Scalar];
2011  Buffer_Recv_Halo = new unsigned short[size*MaxLocalElem];
2012  if (MaxLocalElem > 0) Conn_Elem = new int[size*MaxLocalElem*NODES_PER_ELEMENT];
2013  }
2014 
2015  /*--- Force the removal of all added periodic elements (use global index).
2016  First, we isolate and create a list of all added periodic points, excluding
2017  those that we part of the original domain (we want these to be in the
2018  output files). ---*/
2019 
2020  vector<unsigned long> Added_Periodic;
2021  Added_Periodic.clear();
2022  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
2023  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
2024  SendRecv = config->GetMarker_All_SendRecv(iMarker);
2025  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
2026  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
2027  if ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
2028  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 0) &&
2029  (SendRecv < 0)) {
2030  Added_Periodic.push_back(geometry->node[iPoint]->GetGlobalIndex());
2031  }
2032  }
2033  }
2034  }
2035 
2036  /*--- Now we communicate this information to all processors, so that they
2037  can force the removal of these particular nodes by flagging them as halo
2038  points. In general, this should be a small percentage of the total mesh,
2039  so the communication/storage costs here shouldn't be prohibitive. ---*/
2040 
2041  /*--- First communicate the number of points that each rank has found ---*/
2042  unsigned long nAddedPeriodic = 0, maxAddedPeriodic = 0;
2043  unsigned long Buffer_Send_nAddedPeriodic[1], *Buffer_Recv_nAddedPeriodic = NULL;
2044  Buffer_Recv_nAddedPeriodic = new unsigned long[size];
2045 
2046  nAddedPeriodic = Added_Periodic.size();
2047  Buffer_Send_nAddedPeriodic[0] = nAddedPeriodic;
2048 
2049 #ifdef HAVE_MPI
2050  SU2_MPI::Allreduce(&nAddedPeriodic, &maxAddedPeriodic, 1, MPI_UNSIGNED_LONG,
2052  SU2_MPI::Allgather(&Buffer_Send_nAddedPeriodic, 1, MPI_UNSIGNED_LONG,
2053  Buffer_Recv_nAddedPeriodic, 1, MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
2054 #else
2055  maxAddedPeriodic = nAddedPeriodic;
2056  Buffer_Recv_nAddedPeriodic[0] = Buffer_Send_nAddedPeriodic[0];
2057 #endif
2058 
2059  /*--- Communicate the global index values of all added periodic nodes. ---*/
2060  unsigned long *Buffer_Send_AddedPeriodic = new unsigned long[maxAddedPeriodic];
2061  unsigned long *Buffer_Recv_AddedPeriodic = new unsigned long[size*maxAddedPeriodic];
2062 
2063  for (iPoint = 0; iPoint < Added_Periodic.size(); iPoint++) {
2064  Buffer_Send_AddedPeriodic[iPoint] = Added_Periodic[iPoint];
2065  }
2066 
2067  /*--- Gather the element connectivity information. All processors will now
2068  have a copy of the global index values for all added periodic points. ---*/
2069 
2070 #ifdef HAVE_MPI
2071  SU2_MPI::Allgather(Buffer_Send_AddedPeriodic, maxAddedPeriodic, MPI_UNSIGNED_LONG,
2072  Buffer_Recv_AddedPeriodic, maxAddedPeriodic, MPI_UNSIGNED_LONG,
2073  MPI_COMM_WORLD);
2074 #else
2075  for (iPoint = 0; iPoint < maxAddedPeriodic; iPoint++) Buffer_Recv_AddedPeriodic[iPoint] = Buffer_Send_AddedPeriodic[iPoint];
2076 #endif
2077 
2078  /*--- Search all send/recv boundaries on this partition for halo cells. In
2079  particular, consider only the recv conditions (these are the true halo
2080  nodes). Check the ranks of the processors that are communicating and
2081  choose to keep only the halo cells from the higher rank processor. Here,
2082  we are also choosing to keep periodic nodes that were part of the original
2083  domain. We will check the communicated list of added periodic points. ---*/
2084 
2085  int *Local_Halo = new int[geometry->GetnPoint()];
2086  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
2087  Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain();
2088 
2089  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
2090  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
2091  SendRecv = config->GetMarker_All_SendRecv(iMarker);
2092  RecvFrom = abs(SendRecv)-1;
2093 
2094  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
2095  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
2096  iGlobal_Index = geometry->node[iPoint]->GetGlobalIndex();
2097 
2098  /*--- We need to keep one copy of overlapping halo cells. ---*/
2099  notHalo = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() == 0) &&
2100  (SendRecv < 0) && (rank > RecvFrom));
2101 
2102  /*--- We want to keep the periodic nodes that were part of the original domain ---*/
2103  notPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
2104  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1) &&
2105  (SendRecv < 0));
2106 
2107  /*--- Lastly, check that this isn't an added periodic point that
2108  we will forcibly remove. Use the communicated list of these points. ---*/
2109  addedPeriodic = false; kPoint = 0;
2110  for (iProcessor = 0; iProcessor < size; iProcessor++) {
2111  for (jPoint = 0; jPoint < Buffer_Recv_nAddedPeriodic[iProcessor]; jPoint++) {
2112  if (iGlobal_Index == Buffer_Recv_AddedPeriodic[kPoint+jPoint])
2113  addedPeriodic = true;
2114  }
2115  /*--- Adjust jNode to index of next proc's data in the buffers. ---*/
2116  kPoint = (iProcessor+1)*maxAddedPeriodic;
2117  }
2118 
2119  /*--- If we found either of these types of nodes, flag them to be kept. ---*/
2120  if ((notHalo || notPeriodic) && !addedPeriodic) {
2121  Local_Halo[iPoint] = false;
2122  }
2123  }
2124  }
2125  }
2126 
2127  /*--- Loop over all elements in this partition and load the
2128  elements of the current type into the buffer to be sent to
2129  the master node. ---*/
2130  jNode = 0; jElem = 0;
2131  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++)
2132  if (config->GetMarker_All_Plotting(iMarker) == YES)
2133  for (iElem = 0; iElem < geometry->GetnElem_Bound(iMarker); iElem++) {
2134 
2135  if (geometry->bound[iMarker][iElem]->GetVTK_Type() == Elem_Type) {
2136 
2137  /*--- Loop over all nodes in this element and load the
2138  connectivity into the send buffer. ---*/
2139 
2140  Buffer_Send_Halo[jElem] = false;
2141  for (iNode = 0; iNode < NODES_PER_ELEMENT; iNode++) {
2142 
2143  /*--- Store the global index values directly. ---*/
2144 
2145  iPoint = geometry->bound[iMarker][iElem]->GetNode(iNode);
2146  Buffer_Send_Elem[jNode] = geometry->node[iPoint]->GetGlobalIndex();
2147 
2148  /*--- Check if this is a halo node. If so, flag this element
2149  as a halo cell. We will use this later to sort and remove
2150  any duplicates from the connectivity list. ---*/
2151 
2152  if (Local_Halo[iPoint])
2153  Buffer_Send_Halo[jElem] = true;
2154 
2155  /*--- Increment jNode as the counter. We need this because iElem
2156  may include other elements that we skip over during this loop. ---*/
2157 
2158  jNode++;
2159  }
2160  jElem++;
2161  }
2162  }
2163 
2164  /*--- Gather the element connectivity information. ---*/
2165 
2166 #ifdef HAVE_MPI
2167  SU2_MPI::Gather(Buffer_Send_Elem, nBuffer_Scalar, MPI_UNSIGNED_LONG, Buffer_Recv_Elem, nBuffer_Scalar, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
2168  SU2_MPI::Gather(Buffer_Send_Halo, MaxLocalElem, MPI_UNSIGNED_SHORT, Buffer_Recv_Halo, MaxLocalElem, MPI_UNSIGNED_SHORT, MASTER_NODE, MPI_COMM_WORLD);
2169 #else
2170  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Elem[iPoint] = Buffer_Send_Elem[iPoint];
2171  for (iPoint = 0; iPoint < MaxLocalElem; iPoint++) Buffer_Recv_Halo[iPoint] = Buffer_Send_Halo[iPoint];
2172 #endif
2173 
2174  /*--- The master node unpacks and sorts the connectivity. ---*/
2175 
2176  if (rank == MASTER_NODE) {
2177 
2178  /*--- We need to remove any duplicate elements (halo cells) that
2179  exist on multiple partitions. Start by initializing all elements
2180  to the "write" state by using a boolean array. ---*/
2181 
2182  Write_Elem = new bool[size*MaxLocalElem];
2183  for (iElem = 0; iElem < size*MaxLocalElem; iElem++) {
2184  Write_Elem[iElem] = true;
2185  }
2186 
2187  /*--- Remove the rind layer from the solution only if requested ---*/
2188 
2189  if (!Wrt_Halo) {
2190 
2191  /*--- Loop for flagging duplicate elements so that they are not
2192  included in the final connectivity list. ---*/
2193 
2194  kElem = 0;
2195  for (iProcessor = 0; iProcessor < size; iProcessor++) {
2196  for (iElem = 0; iElem < Buffer_Recv_nElem[iProcessor]; iElem++) {
2197 
2198  /*--- Check if this element was marked as a halo. ---*/
2199  if (Buffer_Recv_Halo[kElem+iElem])
2200  Write_Elem[kElem+iElem] = false;
2201 
2202  }
2203  kElem = (iProcessor+1)*MaxLocalElem;
2204  }
2205  }
2206 
2207  /*--- Store the unique connectivity list for this element type. ---*/
2208 
2209  jNode = 0; kNode = 0; jElem = 0; nElem_Total = 0;
2210  for (iProcessor = 0; iProcessor < size; iProcessor++) {
2211  for (iElem = 0; iElem < Buffer_Recv_nElem[iProcessor]; iElem++) {
2212 
2213  /*--- Only write the elements that were flagged for it. ---*/
2214  if (Write_Elem[jElem+iElem]) {
2215 
2216  /*--- Increment total count for this element type ---*/
2217  nElem_Total++;
2218 
2219  /*--- Get global index, then loop over each variable and store.
2220  Note that we are adding one to the index value because CGNS/Tecplot
2221  use 1-based indexing.---*/
2222 
2223  for (iNode = 0; iNode < NODES_PER_ELEMENT; iNode++) {
2224  Conn_Elem[kNode] = (int)Buffer_Recv_Elem[jNode+iElem*NODES_PER_ELEMENT+iNode] + 1;
2225  kNode++;
2226  }
2227  }
2228  }
2229  /*--- Adjust jNode to index of next proc's data in the buffers. ---*/
2230  jElem = (iProcessor+1)*MaxLocalElem;
2231  jNode = (iProcessor+1)*nBuffer_Scalar;
2232  }
2233  }
2234 
2235  /*--- Immediately release the temporary buffers. ---*/
2236  delete [] Buffer_Send_Elem;
2237  delete [] Buffer_Send_Halo;
2238  delete [] Buffer_Recv_nAddedPeriodic;
2239  delete [] Buffer_Send_AddedPeriodic;
2240  delete [] Buffer_Recv_AddedPeriodic;
2241  delete [] Local_Halo;
2242  if (rank == MASTER_NODE) {
2243  delete [] Buffer_Recv_nElem;
2244  delete [] Buffer_Recv_Elem;
2245  delete [] Buffer_Recv_Halo;
2246  delete [] Write_Elem;
2247  }
2248 
2249  /*--- Store the particular global element count in the class data,
2250  and set the class data pointer to the connectivity array. ---*/
2251 
2252  if (rank == MASTER_NODE) {
2253  switch (Elem_Type) {
2254  case LINE:
2255  nGlobal_Line = nElem_Total;
2256  if (nGlobal_Line > 0) Conn_Line = Conn_Elem;
2257  break;
2258  case TRIANGLE:
2259  nGlobal_BoundTria = nElem_Total;
2260  if (nGlobal_BoundTria > 0) Conn_BoundTria = Conn_Elem;
2261  break;
2262  case QUADRILATERAL:
2263  nGlobal_BoundQuad = nElem_Total;
2264  if (nGlobal_BoundQuad > 0) Conn_BoundQuad = Conn_Elem;
2265  break;
2266  default:
2267  SU2_MPI::Error("Unrecognized element type", CURRENT_FUNCTION);
2268  break;
2269  }
2270  }
2271 
2272 }
2273 
2274 void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone) {
2275 
2276  unsigned short Kind_Solver = config->GetKind_Solver();
2277  unsigned short iVar = 0, jVar = 0, FirstIndex = NONE, SecondIndex = NONE, ThirdIndex = NONE;
2278  unsigned short nVar_First = 0, nVar_Second = 0, nVar_Third = 0;
2279  unsigned short iVar_GridVel = 0, iVar_PressCp = 0, iVar_Lam = 0, iVar_MachMean = 0,
2280  iVar_ViscCoeffs = 0, iVar_HeatCoeffs = 0, iVar_Sens = 0, iVar_Extra = 0, iVar_Eddy = 0, iVar_Sharp = 0,
2281  iVar_FEA_Vel = 0, iVar_FEA_Accel = 0, iVar_FEA_Stress = 0, iVar_FEA_Stress_3D = 0,
2282  iVar_FEA_Extra = 0, iVar_SensDim = 0;
2283  unsigned long iPoint = 0, jPoint = 0, iVertex = 0, iMarker = 0;
2284  su2double Gas_Constant, Mach2Vel, Mach_Motion, RefDensity, RefPressure = 0.0, factor = 0.0;
2285 
2286  su2double *Aux_Frict_x = NULL, *Aux_Frict_y = NULL, *Aux_Frict_z = NULL, *Aux_Heat = NULL, *Aux_yPlus = NULL, *Aux_Sens = NULL;
2287 
2288  unsigned short CurrentIndex;
2289  int *Local_Halo;
2290  unsigned long Buffer_Send_nPoint[1], *Buffer_Recv_nPoint = NULL;
2291  unsigned long nLocalPoint = 0, MaxLocalPoint = 0;
2292  unsigned long iGlobal_Index = 0, nBuffer_Scalar = 0;
2293  bool Wrt_Halo = config->GetWrt_Halo(), isPeriodic;
2294 
2295  int iProcessor;
2296 
2297  bool dynamic_grid = config->GetDynamic_Grid();
2298  bool compressible = (config->GetKind_Regime() == COMPRESSIBLE);
2299  bool incompressible = (config->GetKind_Regime() == INCOMPRESSIBLE);
2300  bool transition = (config->GetKind_Trans_Model() == LM);
2301  bool flow = (( config->GetKind_Solver() == EULER ) ||
2302  ( config->GetKind_Solver() == NAVIER_STOKES ) ||
2303  ( config->GetKind_Solver() == RANS ) ||
2304  ( config->GetKind_Solver() == INC_EULER ) ||
2305  ( config->GetKind_Solver() == INC_NAVIER_STOKES ) ||
2306  ( config->GetKind_Solver() == INC_RANS ) ||
2307  ( config->GetKind_Solver() == FEM_EULER ) ||
2308  ( config->GetKind_Solver() == FEM_NAVIER_STOKES ) ||
2309  ( config->GetKind_Solver() == FEM_RANS ) ||
2310  ( config->GetKind_Solver() == FEM_LES ) ||
2311  ( config->GetKind_Solver() == ADJ_EULER ) ||
2312  ( config->GetKind_Solver() == ADJ_NAVIER_STOKES ) ||
2313  ( config->GetKind_Solver() == ADJ_RANS ) );
2314  bool fem = (config->GetKind_Solver() == FEM_ELASTICITY);
2315 
2316  unsigned short iDim;
2317  unsigned short nDim = geometry->GetnDim();
2318  su2double RefArea = config->GetRefArea();
2319  su2double Gamma = config->GetGamma();
2320  su2double RefVel2, *Normal, Area;
2321 
2322  /*--- Set the non-dimensionalization ---*/
2323  if (flow) {
2324  if (dynamic_grid) {
2325  Gas_Constant = config->GetGas_ConstantND();
2326  Mach2Vel = sqrt(Gamma*Gas_Constant*config->GetTemperature_FreeStreamND());
2327  Mach_Motion = config->GetMach_Motion();
2328  RefVel2 = (Mach_Motion*Mach2Vel)*(Mach_Motion*Mach2Vel);
2329  }
2330  else {
2331  RefVel2 = 0.0;
2332  for (iDim = 0; iDim < nDim; iDim++)
2333  RefVel2 += solver[FLOW_SOL]->GetVelocity_Inf(iDim)*solver[FLOW_SOL]->GetVelocity_Inf(iDim);
2334  }
2335  RefDensity = solver[FLOW_SOL]->GetDensity_Inf();
2336  RefPressure = solver[FLOW_SOL]->GetPressure_Inf();
2337  factor = 1.0 / (0.5*RefDensity*RefArea*RefVel2);
2338  }
2339 
2340  /*--- Prepare send buffers for the conservative variables. Need to
2341  find the total number of conservative variables and also the
2342  index for their particular solution container. ---*/
2343 
2344  switch (Kind_Solver) {
2345  case EULER : case NAVIER_STOKES: case INC_EULER: case INC_NAVIER_STOKES: FirstIndex = FLOW_SOL; if(config->GetWeakly_Coupled_Heat()) SecondIndex = HEAT_SOL; else SecondIndex = NONE; ThirdIndex = NONE; break;
2346  case RANS : case INC_RANS: FirstIndex = FLOW_SOL; SecondIndex = TURB_SOL; if (transition) ThirdIndex=TRANS_SOL; else ThirdIndex = NONE; if(config->GetWeakly_Coupled_Heat()) ThirdIndex = HEAT_SOL; else ThirdIndex = NONE; break;
2347  case FEM_EULER : case FEM_NAVIER_STOKES: case FEM_LES: FirstIndex = FLOW_SOL; SecondIndex = NONE; ThirdIndex = NONE; break;
2348  case FEM_RANS : FirstIndex = FLOW_SOL; SecondIndex = TURB_SOL; break;
2349  case FEM_ELASTICITY: FirstIndex = FEA_SOL; SecondIndex = NONE; ThirdIndex = NONE; break;
2350  case ADJ_EULER : case ADJ_NAVIER_STOKES : FirstIndex = ADJFLOW_SOL; SecondIndex = NONE; ThirdIndex = NONE; break;
2351  case ADJ_RANS : FirstIndex = ADJFLOW_SOL; if (config->GetFrozen_Visc_Cont()) SecondIndex = NONE; else SecondIndex = ADJTURB_SOL; ThirdIndex = NONE; break;
2352  case DISC_ADJ_EULER: case DISC_ADJ_NAVIER_STOKES: case DISC_ADJ_INC_EULER: case DISC_ADJ_INC_NAVIER_STOKES: FirstIndex = ADJFLOW_SOL; SecondIndex = NONE; ThirdIndex = NONE; break;
2353  case DISC_ADJ_RANS: case DISC_ADJ_INC_RANS: FirstIndex = ADJFLOW_SOL; if (config->GetFrozen_Visc_Disc()) SecondIndex = NONE; else SecondIndex = ADJTURB_SOL; ThirdIndex = NONE; break;
2354  case DISC_ADJ_FEM: FirstIndex = ADJFEA_SOL; SecondIndex = NONE; ThirdIndex = NONE; break;
2355  default: SecondIndex = NONE; ThirdIndex = NONE; break;
2356  }
2357 
2358  nVar_First = solver[FirstIndex]->GetnVar();
2359  if (SecondIndex != NONE) nVar_Second = solver[SecondIndex]->GetnVar();
2360  if (ThirdIndex != NONE) nVar_Third = solver[ThirdIndex]->GetnVar();
2361  nVar_Consv = nVar_First + nVar_Second + nVar_Third;
2362  nVar_Total = nVar_Consv;
2363 
2364 
2365  /*--- Add the limiters ---*/
2366 
2367  if (config->GetWrt_Limiters()) nVar_Total += nVar_Consv;
2368 
2369  /*--- Add the residuals ---*/
2370 
2371  if (config->GetWrt_Residuals()) nVar_Total += nVar_Consv;
2372 
2373  /*--- Add the grid velocity to the restart file for the unsteady adjoint ---*/
2374 
2375  if (dynamic_grid && !fem) {
2376  iVar_GridVel = nVar_Total;
2377  if (geometry->GetnDim() == 2) nVar_Total += 2;
2378  else if (geometry->GetnDim() == 3) nVar_Total += 3;
2379  }
2380 
2381  /*--- Add Pressure, Temperature, Cp, Mach to the restart file ---*/
2382 
2383  if (Kind_Solver == EULER || Kind_Solver == NAVIER_STOKES || Kind_Solver == RANS ||
2384  Kind_Solver == INC_EULER || Kind_Solver == INC_NAVIER_STOKES || Kind_Solver == INC_RANS ||
2385  Kind_Solver == FEM_EULER || Kind_Solver == FEM_NAVIER_STOKES || Kind_Solver == FEM_RANS ||
2386  Kind_Solver == FEM_LES) {
2387  iVar_PressCp = nVar_Total; nVar_Total += 3;
2388  iVar_MachMean = nVar_Total; nVar_Total += 1;
2389  }
2390 
2391  /*--- Add Laminar Viscosity, Skin Friction, Heat Flux, & yPlus to the restart file ---*/
2392 
2393  if (Kind_Solver == NAVIER_STOKES || Kind_Solver == RANS ||
2394  Kind_Solver == INC_NAVIER_STOKES || Kind_Solver == INC_RANS ||
2395  Kind_Solver == FEM_NAVIER_STOKES || Kind_Solver == FEM_RANS || Kind_Solver == FEM_LES) {
2396  iVar_Lam = nVar_Total;
2397  nVar_Total += 1;
2398  iVar_ViscCoeffs = nVar_Total;
2399  if (geometry->GetnDim() == 2) nVar_Total += 2;
2400  else if (geometry->GetnDim() == 3) nVar_Total += 3;
2401  iVar_HeatCoeffs = nVar_Total;
2402  nVar_Total += 2;
2403  }
2404 
2405  /*--- Add Eddy Viscosity to the restart file ---*/
2406 
2407  if (Kind_Solver == RANS || Kind_Solver == FEM_RANS || Kind_Solver == FEM_LES || Kind_Solver == INC_RANS) {
2408  iVar_Eddy = nVar_Total; nVar_Total += 1;
2409  }
2410 
2411  /*--- Add Sharp edges to the restart file ---*/
2412 
2413  if (config->GetWrt_SharpEdges()) {
2414  if (((Kind_Solver == EULER) || (Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) ||
2415  ((Kind_Solver == INC_EULER) || (Kind_Solver == INC_NAVIER_STOKES) || (Kind_Solver == INC_RANS)) ||
2416  ((Kind_Solver == FEM_EULER) || (Kind_Solver == FEM_NAVIER_STOKES) || (Kind_Solver == FEM_RANS) || (Kind_Solver == FEM_LES))) {
2417  iVar_Sharp = nVar_Total; nVar_Total += 1;
2418  }
2419  }
2420 
2421 
2422  if (( Kind_Solver == ADJ_EULER ) ||
2423  ( Kind_Solver == ADJ_NAVIER_STOKES ) ||
2424  ( Kind_Solver == ADJ_RANS )) {
2425  iVar_Sens = nVar_Total; nVar_Total += 2;
2426  }
2427 
2428  if (Kind_Solver == FEM_ELASTICITY) {
2429  /*--- If the analysis is dynamic... ---*/
2430  if (config->GetTime_Domain()) {
2431  /*--- Velocities ---*/
2432  iVar_FEA_Vel = nVar_Total;
2433  if (geometry->GetnDim() == 2) nVar_Total += 2;
2434  else if (geometry->GetnDim() == 3) nVar_Total += 3;
2435  /*--- Accelerations ---*/
2436  iVar_FEA_Accel = nVar_Total;
2437  if (geometry->GetnDim() == 2) nVar_Total += 2;
2438  else if (geometry->GetnDim() == 3) nVar_Total += 3;
2439  }
2440  iVar_FEA_Stress = nVar_Total; nVar_Total += 3;
2441  if (geometry->GetnDim() == 3) {iVar_FEA_Stress_3D = nVar_Total; nVar_Total += 3;}
2442  iVar_FEA_Extra = nVar_Total; nVar_Total += 1;
2443  }
2444 
2445  if ((Kind_Solver == DISC_ADJ_EULER) ||
2446  (Kind_Solver == DISC_ADJ_NAVIER_STOKES) ||
2447  (Kind_Solver == DISC_ADJ_RANS) ||
2448  (Kind_Solver == DISC_ADJ_INC_EULER) ||
2449  (Kind_Solver == DISC_ADJ_INC_NAVIER_STOKES) ||
2450  (Kind_Solver == DISC_ADJ_INC_RANS)) {
2451  iVar_Sens = nVar_Total; nVar_Total += 1;
2452  iVar_SensDim = nVar_Total; nVar_Total += nDim;
2453  }
2454 
2455  if ((Kind_Solver == DISC_ADJ_FEM) && (config->GetFSI_Simulation())){
2456  iVar_FEA_Extra = nVar_Total; nVar_Total += 2;
2457  }
2458 
2459  if (config->GetExtraOutput()) {
2460  if (Kind_Solver == RANS || Kind_Solver == INC_RANS) {
2461  iVar_Extra = nVar_Total; nVar_Extra = solver[TURB_SOL]->GetnOutputVariables(); nVar_Total += nVar_Extra;
2462  }
2463  }
2464 
2465 
2466 
2467  Local_Halo = new int[geometry->GetnPoint()];
2468  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
2469  Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain();
2470 
2471  /*--- Search all send/recv boundaries on this partition for any periodic
2472  nodes that were part of the original domain. We want to recover these
2473  for visualization purposes. ---*/
2474 
2475  if (Wrt_Halo) {
2476  nLocalPoint = geometry->GetnPoint();
2477  } else {
2478  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
2479  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
2480 
2481  /*--- Checking for less than or equal to the rank, because there may
2482  be some periodic halo nodes that send info to the same rank. ---*/
2483 
2484  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
2485  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
2486  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
2487  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1));
2488  if (isPeriodic) Local_Halo[iPoint] = false;
2489  }
2490  }
2491  }
2492 
2493  /*--- Sum total number of nodes that belong to the domain ---*/
2494 
2495  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
2496  if (Local_Halo[iPoint] == false)
2497  nLocalPoint++;
2498 
2499  }
2500  Buffer_Send_nPoint[0] = nLocalPoint;
2501 
2502  /*--- Each processor sends its local number of nodes to the master. ---*/
2503 
2504  if (rank == MASTER_NODE) Buffer_Recv_nPoint = new unsigned long[size];
2505 
2506 #ifdef HAVE_MPI
2507  SU2_MPI::Allreduce(&nLocalPoint, &MaxLocalPoint, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
2508  SU2_MPI::Gather(&Buffer_Send_nPoint, 1, MPI_UNSIGNED_LONG, Buffer_Recv_nPoint, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
2509 #else
2510  MaxLocalPoint = nLocalPoint;
2511  Buffer_Recv_nPoint[0] = Buffer_Send_nPoint[0];
2512 #endif
2513 
2514  nBuffer_Scalar = MaxLocalPoint;
2515 
2516  /*--- Send and Recv buffers. ---*/
2517 
2518  su2double *Buffer_Send_Var = new su2double[MaxLocalPoint];
2519  su2double *Buffer_Recv_Var = NULL;
2520 
2521  su2double *Buffer_Send_Res = new su2double[MaxLocalPoint];
2522  su2double *Buffer_Recv_Res = NULL;
2523 
2524  su2double *Buffer_Send_Vol = new su2double[MaxLocalPoint];
2525  su2double *Buffer_Recv_Vol = NULL;
2526 
2527  unsigned long *Buffer_Send_GlobalIndex = new unsigned long[MaxLocalPoint];
2528  unsigned long *Buffer_Recv_GlobalIndex = NULL;
2529 
2530  /*--- Auxiliary vectors for surface coefficients ---*/
2531 
2532  if (((Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) ||
2533  ((Kind_Solver == INC_NAVIER_STOKES) || (Kind_Solver == INC_RANS)) ||
2534  ((Kind_Solver == FEM_NAVIER_STOKES) || (Kind_Solver == FEM_RANS) || (Kind_Solver == FEM_LES))) {
2535  Aux_Frict_x = new su2double[geometry->GetnPoint()];
2536  Aux_Frict_y = new su2double[geometry->GetnPoint()];
2537  Aux_Frict_z = new su2double[geometry->GetnPoint()];
2538  Aux_Heat = new su2double[geometry->GetnPoint()];
2539  Aux_yPlus = new su2double[geometry->GetnPoint()];
2540  }
2541 
2542  if ((Kind_Solver == ADJ_EULER) ||
2543  (Kind_Solver == ADJ_NAVIER_STOKES) ||
2544  (Kind_Solver == ADJ_RANS) ||
2545  (Kind_Solver == DISC_ADJ_EULER) ||
2546  (Kind_Solver == DISC_ADJ_NAVIER_STOKES) ||
2547  (Kind_Solver == DISC_ADJ_RANS) ||
2548  (Kind_Solver == DISC_ADJ_INC_EULER) ||
2549  (Kind_Solver == DISC_ADJ_INC_NAVIER_STOKES) ||
2550  (Kind_Solver == DISC_ADJ_INC_RANS)) {
2551  Aux_Sens = new su2double[geometry->GetnPoint()];
2552  }
2553 
2554  /*--- Prepare the receive buffers in the master node only. ---*/
2555 
2556  if (rank == MASTER_NODE) {
2557 
2558  Buffer_Recv_Var = new su2double[size*MaxLocalPoint];
2559  Buffer_Recv_Res = new su2double[size*MaxLocalPoint];
2560  Buffer_Recv_Vol = new su2double[size*MaxLocalPoint];
2561  Buffer_Recv_GlobalIndex = new unsigned long[size*MaxLocalPoint];
2562 
2563  /*--- Sum total number of nodes to be written and allocate arrays ---*/
2564  nGlobal_Poin = 0;
2565  for (iProcessor = 0; iProcessor < size; iProcessor++) {
2566  nGlobal_Poin += Buffer_Recv_nPoint[iProcessor];
2567  }
2568  Data = new su2double*[nVar_Total];
2569  for (iVar = 0; iVar < nVar_Total; iVar++) {
2570  Data[iVar] = new su2double[nGlobal_Poin];
2571  }
2572  }
2573 
2574  /*--- Main communication routine. Loop over each variable that has
2575  been requested by the user and perform the MPI comm. Temporary
2576  1-D buffers are used to send the solution for each variable at all
2577  nodes on each partition to the master node. These are then unpacked
2578  by the master and sorted by global index in one large n-dim. array. ---*/
2579 
2580  for (iVar = 0; iVar < nVar_Consv; iVar++) {
2581 
2582  /*--- Logic for which solution class to draw from. ---*/
2583 
2584  jVar = iVar;
2585  CurrentIndex = FirstIndex;
2586  if ((SecondIndex != NONE) && (iVar > nVar_First-1)) {
2587  jVar = iVar - nVar_First;
2588  CurrentIndex = SecondIndex;
2589  }
2590  if ((SecondIndex != NONE) && (ThirdIndex != NONE) && (iVar > (nVar_First + nVar_Second-1))) {
2591  jVar = iVar - nVar_First - nVar_Second;
2592  CurrentIndex = ThirdIndex;
2593  }
2594 
2595  /*--- Loop over this partition to collect the current variable ---*/
2596 
2597  jPoint = 0;
2598  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
2599 
2600  /*--- Check for halos & write only if requested ---*/
2601 
2602  if (!Local_Halo[iPoint] || Wrt_Halo) {
2603 
2604  /*--- Get this variable into the temporary send buffer. ---*/
2605 
2606  Buffer_Send_Var[jPoint] = solver[CurrentIndex]->GetNodes()->GetSolution(iPoint, jVar);
2607 
2608 
2609  if (config->GetWrt_Limiters()) {
2610  Buffer_Send_Vol[jPoint] = solver[CurrentIndex]->GetNodes()->GetLimiter_Primitive(iPoint, jVar);
2611  }
2612 
2613  if (config->GetWrt_Residuals()) {
2614  if (!config->GetDiscrete_Adjoint()) {
2615  Buffer_Send_Res[jPoint] = solver[CurrentIndex]->LinSysRes.GetBlock(iPoint, jVar);
2616  } else {
2617  Buffer_Send_Res[jPoint] = solver[CurrentIndex]->GetNodes()->GetSolution(iPoint, jVar) -
2618  solver[CurrentIndex]->GetNodes()->GetSolution_Old(iPoint, jVar);
2619  }
2620  }
2621 
2622 
2623  /*--- Only send/recv the volumes & global indices during the first loop ---*/
2624 
2625  if (iVar == 0) {
2626  Buffer_Send_GlobalIndex[jPoint] = geometry->node[iPoint]->GetGlobalIndex();
2627  }
2628 
2629  jPoint++;
2630 
2631  }
2632  }
2633 
2634  /*--- Gather the data on the master node. ---*/
2635 
2636 #ifdef HAVE_MPI
2637  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
2638 #else
2639  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint];
2640 #endif
2641 
2642  if (config->GetWrt_Limiters()) {
2643 #ifdef HAVE_MPI
2644  SU2_MPI::Gather(Buffer_Send_Vol, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Vol, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
2645 #else
2646  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Vol[iPoint] = Buffer_Send_Vol[iPoint];
2647 #endif
2648  }
2649 
2650  if (config->GetWrt_Residuals()) {
2651 #ifdef HAVE_MPI
2652  SU2_MPI::Gather(Buffer_Send_Res, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Res, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
2653 #else
2654  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Res[iPoint] = Buffer_Send_Res[iPoint];
2655 #endif
2656  }
2657 
2658 
2659 
2660  if (iVar == 0) {
2661 #ifdef HAVE_MPI
2662  SU2_MPI::Gather(Buffer_Send_GlobalIndex, nBuffer_Scalar, MPI_UNSIGNED_LONG, Buffer_Recv_GlobalIndex, nBuffer_Scalar, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
2663 #else
2664  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_GlobalIndex[iPoint] = Buffer_Send_GlobalIndex[iPoint];
2665 #endif
2666  }
2667 
2668  /*--- The master node unpacks and sorts this variable by global index ---*/
2669 
2670  if (rank == MASTER_NODE) {
2671  jPoint = 0;
2672  for (iProcessor = 0; iProcessor < size; iProcessor++) {
2673  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
2674 
2675  /*--- Get global index, then loop over each variable and store ---*/
2676 
2677  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
2678 
2679  Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint];
2680 
2681 
2682  if (config->GetWrt_Limiters()) {
2683  Data[iVar+nVar_Consv][iGlobal_Index] = Buffer_Recv_Vol[jPoint];
2684  }
2685 
2686  if (config->GetWrt_Residuals()) {
2687  unsigned short ExtraIndex;
2688  ExtraIndex = nVar_Consv;
2689  if (config->GetWrt_Limiters()) ExtraIndex = 2*nVar_Consv;
2690  Data[iVar+ExtraIndex][iGlobal_Index] = Buffer_Recv_Res[jPoint];
2691  }
2692 
2693 
2694 
2695  jPoint++;
2696  }
2697  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
2698  jPoint = (iProcessor+1)*nBuffer_Scalar;
2699  }
2700  }
2701 
2702  }
2703 
2704  /*--- Additional communication routine for the grid velocity. Note that
2705  we are reusing the same temporary buffers from above for efficiency.
2706  Also, in the future more routines like this could be used to write
2707  an arbitrary number of additional variables to the file. ---*/
2708 
2709  if (dynamic_grid && !fem) {
2710 
2711  /*--- Loop over this partition to collect the current variable ---*/
2712 
2713  jPoint = 0; su2double *Grid_Vel;
2714  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
2715 
2716  /*--- Check for halos & write only if requested ---*/
2717 
2718  if (!Local_Halo[iPoint] || Wrt_Halo) {
2719 
2720  /*--- Load buffers with the three grid velocity components. ---*/
2721 
2722  Grid_Vel = geometry->node[iPoint]->GetGridVel();
2723  Buffer_Send_Var[jPoint] = Grid_Vel[0];
2724  Buffer_Send_Res[jPoint] = Grid_Vel[1];
2725  if (geometry->GetnDim() == 3) Buffer_Send_Vol[jPoint] = Grid_Vel[2];
2726  jPoint++;
2727  }
2728  }
2729 
2730  /*--- Gather the data on the master node. ---*/
2731 
2732 #ifdef HAVE_MPI
2733  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
2734  SU2_MPI::Gather(Buffer_Send_Res, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Res, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
2735  if (geometry->GetnDim() == 3) {
2736  SU2_MPI::Gather(Buffer_Send_Vol, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Vol, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
2737  }
2738 #else
2739  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint];
2740  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Res[iPoint] = Buffer_Send_Res[iPoint];
2741  if (geometry->GetnDim() == 3) {
2742  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Vol[iPoint] = Buffer_Send_Vol[iPoint];
2743  }
2744 #endif
2745 
2746  /*--- The master node unpacks and sorts this variable by global index ---*/
2747 
2748  if (rank == MASTER_NODE) {
2749  jPoint = 0; iVar = iVar_GridVel;
2750  for (iProcessor = 0; iProcessor < size; iProcessor++) {
2751  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
2752 
2753  /*--- Get global index, then loop over each variable and store ---*/
2754 
2755  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
2756  Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint];
2757  Data[iVar+1][iGlobal_Index] = Buffer_Recv_Res[jPoint];
2758  if (geometry->GetnDim() == 3)
2759  Data[iVar+2][iGlobal_Index] = Buffer_Recv_Vol[jPoint];
2760  jPoint++;
2761  }
2762 
2763  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
2764 
2765  jPoint = (iProcessor+1)*nBuffer_Scalar;
2766  }
2767  }
2768  }
2769 
2770  /*--- Communicate Pressure, Cp, and Mach ---*/
2771 
2772  if (((Kind_Solver == EULER) || (Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) ||
2773  ((Kind_Solver == INC_EULER) || (Kind_Solver == INC_NAVIER_STOKES) || (Kind_Solver == INC_RANS)) ||
2774  ((Kind_Solver == FEM_EULER) || (Kind_Solver == FEM_NAVIER_STOKES) || (Kind_Solver == FEM_RANS) || (Kind_Solver == FEM_LES))) {
2775 
2776  /*--- First, loop through the mesh in order to find and store the
2777  value of the coefficient of pressure at any surface nodes. They
2778  will be placed in an auxiliary vector and then communicated like
2779  all other volumetric variables. ---*/
2780 
2781  /*--- Loop over this partition to collect the current variable ---*/
2782 
2783  jPoint = 0;
2784  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
2785 
2786  /*--- Check for halos & write only if requested ---*/
2787 
2788  if (!Local_Halo[iPoint] || Wrt_Halo) {
2789 
2790  /*--- Load buffers with the pressure, Cp, and mach variables. ---*/
2791 
2792  Buffer_Send_Var[jPoint] = solver[FLOW_SOL]->GetNodes()->GetPressure(iPoint);
2793  if (compressible){
2794  Buffer_Send_Res[jPoint] = solver[FLOW_SOL]->GetNodes()->GetTemperature(iPoint);
2795  } else{
2796  Buffer_Send_Res[jPoint] = 0.0;
2797  }
2798  Buffer_Send_Vol[jPoint] = (solver[FLOW_SOL]->GetNodes()->GetPressure(iPoint) - RefPressure)*factor*RefArea;
2799 
2800  jPoint++;
2801  }
2802  }
2803 
2804  /*--- Gather the data on the master node. ---*/
2805 
2806 #ifdef HAVE_MPI
2807  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
2808  SU2_MPI::Gather(Buffer_Send_Res, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Res, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
2809  SU2_MPI::Gather(Buffer_Send_Vol, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Vol, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
2810 #else
2811  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint];
2812  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Res[iPoint] = Buffer_Send_Res[iPoint];
2813  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Vol[iPoint] = Buffer_Send_Vol[iPoint];
2814 #endif
2815 
2816  /*--- The master node unpacks and sorts this variable by global index ---*/
2817 
2818  if (rank == MASTER_NODE) {
2819  jPoint = 0; iVar = iVar_PressCp;
2820  for (iProcessor = 0; iProcessor < size; iProcessor++) {
2821  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
2822 
2823  /*--- Get global index, then loop over each variable and store ---*/
2824 
2825  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
2826  Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint];
2827  Data[iVar+1][iGlobal_Index] = Buffer_Recv_Res[jPoint];
2828  Data[iVar+2][iGlobal_Index] = Buffer_Recv_Vol[jPoint];
2829  jPoint++;
2830  }
2831 
2832  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
2833 
2834  jPoint = (iProcessor+1)*nBuffer_Scalar;
2835  }
2836  }
2837  }
2838 
2839  /*--- Communicate Mach---*/
2840 
2841  if (((Kind_Solver == EULER) || (Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) ||
2842  ((Kind_Solver == INC_EULER) || (Kind_Solver == INC_NAVIER_STOKES) || (Kind_Solver == INC_RANS)) ||
2843  ((Kind_Solver == FEM_EULER) || (Kind_Solver == FEM_NAVIER_STOKES) || (Kind_Solver == FEM_RANS) || (Kind_Solver == FEM_LES))) {
2844 
2845  /*--- Loop over this partition to collect the current variable ---*/
2846 
2847  jPoint = 0;
2848  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
2849 
2850  /*--- Check for halos & write only if requested ---*/
2851 
2852  if (!Local_Halo[iPoint] || Wrt_Halo) {
2853 
2854  /*--- Load buffers with the temperature and laminar viscosity variables. ---*/
2855 
2856  if (compressible) {
2857  Buffer_Send_Var[jPoint] = sqrt(solver[FLOW_SOL]->GetNodes()->GetVelocity2(iPoint))/
2858  solver[FLOW_SOL]->GetNodes()->GetSoundSpeed(iPoint);
2859  }
2860  if (incompressible) {
2861  Buffer_Send_Var[jPoint] = sqrt(solver[FLOW_SOL]->GetNodes()->GetVelocity2(iPoint))*config->GetVelocity_Ref()/
2862  sqrt(config->GetBulk_Modulus()/(solver[FLOW_SOL]->GetNodes()->GetDensity(iPoint)*config->GetDensity_Ref()));
2863  }
2864  jPoint++;
2865  }
2866  }
2867 
2868  /*--- Gather the data on the master node. ---*/
2869 
2870 #ifdef HAVE_MPI
2871  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
2872 #else
2873  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint];
2874 #endif
2875 
2876  /*--- The master node unpacks and sorts this variable by global index ---*/
2877 
2878  if (rank == MASTER_NODE) {
2879  jPoint = 0; iVar = iVar_MachMean;
2880  for (iProcessor = 0; iProcessor < size; iProcessor++) {
2881  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
2882 
2883  /*--- Get global index, then loop over each variable and store ---*/
2884 
2885  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
2886  Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint];
2887  jPoint++;
2888  }
2889 
2890  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
2891 
2892  jPoint = (iProcessor+1)*nBuffer_Scalar;
2893  }
2894  }
2895  }
2896 
2897  /*--- Laminar Viscosity ---*/
2898 
2899  if (((Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) ||
2900  ((Kind_Solver == INC_NAVIER_STOKES) || (Kind_Solver == INC_RANS)) ||
2901  ((Kind_Solver == FEM_NAVIER_STOKES) || (Kind_Solver == FEM_RANS) || (Kind_Solver == FEM_LES))) {
2902 
2903  /*--- Loop over this partition to collect the current variable ---*/
2904 
2905  jPoint = 0;
2906  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
2907 
2908  /*--- Check for halos & write only if requested ---*/
2909 
2910  if (!Local_Halo[iPoint] || Wrt_Halo) {
2911 
2912  /*--- Load buffers with the temperature and laminar viscosity variables. ---*/
2913 
2914  Buffer_Send_Res[jPoint] = solver[FLOW_SOL]->GetNodes()->GetLaminarViscosity(iPoint);
2915 
2916  jPoint++;
2917  }
2918  }
2919 
2920  /*--- Gather the data on the master node. ---*/
2921 
2922 #ifdef HAVE_MPI
2923  SU2_MPI::Gather(Buffer_Send_Res, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Res, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
2924 #else
2925  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Res[iPoint] = Buffer_Send_Res[iPoint];
2926 #endif
2927 
2928  /*--- The master node unpacks and sorts this variable by global index ---*/
2929 
2930  if (rank == MASTER_NODE) {
2931  jPoint = 0; iVar = iVar_Lam;
2932  for (iProcessor = 0; iProcessor < size; iProcessor++) {
2933  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
2934 
2935  /*--- Get global index, then loop over each variable and store ---*/
2936 
2937  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
2938  Data[iVar][iGlobal_Index] = Buffer_Recv_Res[jPoint];
2939  jPoint++;
2940  }
2941 
2942  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
2943 
2944  jPoint = (iProcessor+1)*nBuffer_Scalar;
2945  }
2946  }
2947 
2948  /*--- Communicate skin friction ---*/
2949 
2950  /*--- First, loop through the mesh in order to find and store the
2951  value of the viscous coefficients at any surface nodes. They
2952  will be placed in an auxiliary vector and then communicated like
2953  all other volumetric variables. ---*/
2954 
2955  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
2956  Aux_Frict_x[iPoint] = 0.0;
2957  Aux_Frict_y[iPoint] = 0.0;
2958  Aux_Frict_z[iPoint] = 0.0;
2959  }
2960  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++)
2961  if (config->GetMarker_All_Plotting(iMarker) == YES) {
2962  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
2963  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
2964  Aux_Frict_x[iPoint] = solver[FLOW_SOL]->GetCSkinFriction(iMarker, iVertex, 0);
2965  Aux_Frict_y[iPoint] = solver[FLOW_SOL]->GetCSkinFriction(iMarker, iVertex, 1);
2966  if (geometry->GetnDim() == 3) Aux_Frict_z[iPoint] = solver[FLOW_SOL]->GetCSkinFriction(iMarker, iVertex, 2);
2967  }
2968  }
2969 
2970  /*--- Loop over this partition to collect the current variable ---*/
2971 
2972  jPoint = 0;
2973  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
2974 
2975  /*--- Check for halos & write only if requested ---*/
2976 
2977  if (!Local_Halo[iPoint] || Wrt_Halo) {
2978 
2979  /*--- Load buffers with the three grid velocity components. ---*/
2980 
2981  Buffer_Send_Var[jPoint] = Aux_Frict_x[iPoint];
2982  Buffer_Send_Res[jPoint] = Aux_Frict_y[iPoint];
2983  if (geometry->GetnDim() == 3)
2984  Buffer_Send_Vol[jPoint] = Aux_Frict_z[iPoint];
2985  jPoint++;
2986  }
2987  }
2988 
2989  /*--- Gather the data on the master node. ---*/
2990 
2991 #ifdef HAVE_MPI
2992  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
2993  SU2_MPI::Gather(Buffer_Send_Res, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Res, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
2994  if (geometry->GetnDim() == 3) {
2995  SU2_MPI::Gather(Buffer_Send_Vol, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Vol, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
2996  }
2997 #else
2998  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++)
2999  Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint];
3000  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++)
3001  Buffer_Recv_Res[iPoint] = Buffer_Send_Res[iPoint];
3002  if (geometry->GetnDim() == 3) {
3003  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++)
3004  Buffer_Recv_Vol[iPoint] = Buffer_Send_Vol[iPoint];
3005  }
3006 #endif
3007 
3008  /*--- The master node unpacks and sorts this variable by global index ---*/
3009 
3010  if (rank == MASTER_NODE) {
3011  jPoint = 0;
3012  iVar = iVar_ViscCoeffs;
3013  for (iProcessor = 0; iProcessor < size; iProcessor++) {
3014  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
3015 
3016  /*--- Get global index, then loop over each variable and store ---*/
3017 
3018  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
3019  Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint];
3020  Data[iVar + 1][iGlobal_Index] = Buffer_Recv_Res[jPoint];
3021  if (geometry->GetnDim() == 3)
3022  Data[iVar + 2][iGlobal_Index] = Buffer_Recv_Vol[jPoint];
3023  jPoint++;
3024  }
3025 
3026  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
3027 
3028  jPoint = (iProcessor + 1) * nBuffer_Scalar;
3029  }
3030  }
3031 
3032  /*--- Communicate heat transfer, y+ ---*/
3033 
3034  /*--- First, loop through the mesh in order to find and store the
3035  value of the viscous coefficients at any surface nodes. They
3036  will be placed in an auxiliary vector and then communicated like
3037  all other volumetric variables. ---*/
3038 
3039  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
3040  Aux_Heat[iPoint] = 0.0;
3041  Aux_yPlus[iPoint] = 0.0;
3042  }
3043  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++)
3044  if (config->GetMarker_All_Plotting(iMarker) == YES) {
3045  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
3046  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
3047  Aux_Heat[iPoint] = solver[FLOW_SOL]->GetHeatFlux(iMarker, iVertex);
3048  Aux_yPlus[iPoint] = solver[FLOW_SOL]->GetYPlus(iMarker, iVertex);
3049  }
3050  }
3051 
3052  /*--- Loop over this partition to collect the current variable ---*/
3053 
3054  jPoint = 0;
3055  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
3056 
3057  /*--- Check for halos & write only if requested ---*/
3058 
3059  if (!Local_Halo[iPoint] || Wrt_Halo) {
3060 
3061  /*--- Load buffers with the skin friction, heat transfer, y+ variables. ---*/
3062 
3063  if (compressible) {
3064  Buffer_Send_Res[jPoint] = Aux_Heat[iPoint];
3065  Buffer_Send_Vol[jPoint] = Aux_yPlus[iPoint];
3066  }
3067  if (incompressible) {
3068  Buffer_Send_Res[jPoint] = Aux_Heat[iPoint];
3069  Buffer_Send_Vol[jPoint] = Aux_yPlus[iPoint];
3070  }
3071  jPoint++;
3072  }
3073  }
3074 
3075  /*--- Gather the data on the master node. ---*/
3076 
3077 #ifdef HAVE_MPI
3078  SU2_MPI::Gather(Buffer_Send_Res, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Res, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3079  SU2_MPI::Gather(Buffer_Send_Vol, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Vol, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3080 #else
3081  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++)
3082  Buffer_Recv_Res[iPoint] = Buffer_Send_Res[iPoint];
3083  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++)
3084  Buffer_Recv_Vol[iPoint] = Buffer_Send_Vol[iPoint];
3085 #endif
3086 
3087  /*--- The master node unpacks and sorts this variable by global index ---*/
3088 
3089  if (rank == MASTER_NODE) {
3090  jPoint = 0;
3091  iVar = iVar_HeatCoeffs;
3092 
3093  for (iProcessor = 0; iProcessor < size; iProcessor++) {
3094  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
3095 
3096  /*--- Get global index, then loop over each variable and store ---*/
3097 
3098  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
3099  Data[iVar + 0][iGlobal_Index] = Buffer_Recv_Res[jPoint];
3100  Data[iVar + 1][iGlobal_Index] = Buffer_Recv_Vol[jPoint];
3101  jPoint++;
3102  }
3103 
3104  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
3105 
3106  jPoint = (iProcessor + 1) * nBuffer_Scalar;
3107  }
3108  }
3109  }
3110 
3111 
3112  /*--- Communicate the Eddy Viscosity ---*/
3113 
3114  if (Kind_Solver == RANS || Kind_Solver == FEM_RANS || Kind_Solver == FEM_LES || Kind_Solver == INC_RANS) {
3115 
3116  /*--- Loop over this partition to collect the current variable ---*/
3117 
3118  jPoint = 0;
3119  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
3120 
3121  /*--- Check for halos & write only if requested ---*/
3122 
3123  if (!Local_Halo[iPoint] || Wrt_Halo) {
3124 
3125  /*--- Load buffers with the pressure and mach variables. ---*/
3126 
3127  Buffer_Send_Var[jPoint] = solver[FLOW_SOL]->GetNodes()->GetEddyViscosity(iPoint);
3128 
3129  jPoint++;
3130  }
3131  }
3132 
3133  /*--- Gather the data on the master node. ---*/
3134 
3135 #ifdef HAVE_MPI
3136  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3137 #else
3138  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint];
3139 #endif
3140 
3141  /*--- The master node unpacks and sorts this variable by global index ---*/
3142 
3143  if (rank == MASTER_NODE) {
3144  jPoint = 0; iVar = iVar_Eddy;
3145  for (iProcessor = 0; iProcessor < size; iProcessor++) {
3146  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
3147 
3148  /*--- Get global index, then loop over each variable and store ---*/
3149 
3150  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
3151  Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint];
3152  jPoint++;
3153  }
3154 
3155  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
3156 
3157  jPoint = (iProcessor+1)*nBuffer_Scalar;
3158  }
3159  }
3160 
3161  }
3162 
3163  /*--- Communicate the Sharp Edges ---*/
3164 
3165  if (config->GetWrt_SharpEdges()) {
3166 
3167  if (((Kind_Solver == EULER) || (Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) ||
3168  ((Kind_Solver == INC_EULER) || (Kind_Solver == INC_NAVIER_STOKES) || (Kind_Solver == INC_RANS)) ||
3169  ((Kind_Solver == FEM_EULER) || (Kind_Solver == FEM_NAVIER_STOKES) || (Kind_Solver == FEM_RANS) || (Kind_Solver == FEM_LES))) {
3170 
3171  /*--- Loop over this partition to collect the current variable ---*/
3172  jPoint = 0;
3173  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
3174 
3175  /*--- Check for halos & write only if requested ---*/
3176 
3177  if (!Local_Halo[iPoint] || Wrt_Halo) {
3178 
3179  /*--- Load buffers with the pressure and mach variables. ---*/
3180 
3181  Buffer_Send_Var[jPoint] = geometry->node[iPoint]->GetSharpEdge_Distance();
3182  jPoint++;
3183  }
3184  }
3185 
3186  /*--- Gather the data on the master node. ---*/
3187 
3188 #ifdef HAVE_MPI
3189  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3190 #else
3191  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint];
3192 #endif
3193 
3194  /*--- The master node unpacks and sorts this variable by global index ---*/
3195 
3196  if (rank == MASTER_NODE) {
3197  jPoint = 0; iVar = iVar_Sharp;
3198  for (iProcessor = 0; iProcessor < size; iProcessor++) {
3199  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
3200 
3201  /*--- Get global index, then loop over each variable and store ---*/
3202 
3203  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
3204  Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint];
3205  jPoint++;
3206  }
3207 
3208  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
3209 
3210  jPoint = (iProcessor+1)*nBuffer_Scalar;
3211  }
3212  }
3213  }
3214  }
3215 
3216  /*--- Communicate the surface sensitivity ---*/
3217 
3218  if ((Kind_Solver == ADJ_EULER) ||
3219  (Kind_Solver == ADJ_NAVIER_STOKES) ||
3220  (Kind_Solver == ADJ_RANS) ||
3221  (Kind_Solver == DISC_ADJ_EULER) ||
3222  (Kind_Solver == DISC_ADJ_NAVIER_STOKES) ||
3223  (Kind_Solver == DISC_ADJ_RANS) ||
3224  (Kind_Solver == DISC_ADJ_INC_EULER) ||
3225  (Kind_Solver == DISC_ADJ_INC_NAVIER_STOKES) ||
3226  (Kind_Solver == DISC_ADJ_INC_RANS)) {
3227 
3228  /*--- First, loop through the mesh in order to find and store the
3229  value of the surface sensitivity at any surface nodes. They
3230  will be placed in an auxiliary vector and then communicated like
3231  all other volumetric variables. ---*/
3232 
3233  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) Aux_Sens[iPoint] = 0.0;
3234  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++)
3235  if (config->GetMarker_All_Plotting(iMarker) == YES) {
3236  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
3237  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
3238  Normal = geometry->vertex[iMarker][iVertex]->GetNormal();
3239  Area = 0.0;
3240  for (iDim = 0; iDim < nDim; iDim++) Area += Normal[iDim]*Normal[iDim];
3241  Area = sqrt (Area);
3242  Aux_Sens[iPoint] = solver[ADJFLOW_SOL]->GetCSensitivity(iMarker, iVertex)/Area;
3243  }
3244  }
3245 
3246  /*--- Loop over this partition to collect the current variable ---*/
3247 
3248  jPoint = 0;
3249  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
3250 
3251  /*--- Check for halos & write only if requested ---*/
3252 
3253  if (!Local_Halo[iPoint] || Wrt_Halo) {
3254 
3255  /*--- Load buffers with the skin friction, heat transfer, y+ variables. ---*/
3256 
3257  Buffer_Send_Var[jPoint] = Aux_Sens[iPoint];
3258  if ((config->GetKind_ConvNumScheme() == SPACE_CENTERED) && (!config->GetDiscrete_Adjoint()))
3259  Buffer_Send_Res[jPoint] = solver[ADJFLOW_SOL]->GetNodes()->GetSensor(iPoint, iPoint);
3260  if ((config->GetKind_ConvNumScheme() == SPACE_UPWIND) && (!config->GetDiscrete_Adjoint()))
3261  Buffer_Send_Res[jPoint] = solver[ADJFLOW_SOL]->GetNodes()->GetLimiter(iPoint, 0);
3262 
3263  jPoint++;
3264  }
3265  }
3266 
3267  /*--- Gather the data on the master node. ---*/
3268 
3269 #ifdef HAVE_MPI
3270  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3271  if (!config->GetDiscrete_Adjoint())
3272  SU2_MPI::Gather(Buffer_Send_Res, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Res, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3273 #else
3274  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint];
3275  if (!config->GetDiscrete_Adjoint())
3276  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Res[iPoint] = Buffer_Send_Res[iPoint];
3277 #endif
3278 
3279  /*--- The master node unpacks and sorts this variable by global index ---*/
3280 
3281  if (rank == MASTER_NODE) {
3282  jPoint = 0; iVar = iVar_Sens;
3283  for (iProcessor = 0; iProcessor < size; iProcessor++) {
3284  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
3285 
3286  /*--- Get global index, then loop over each variable and store ---*/
3287 
3288  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
3289  Data[iVar+0][iGlobal_Index] = Buffer_Recv_Var[jPoint];
3290  if (!config->GetDiscrete_Adjoint())
3291  Data[iVar+1][iGlobal_Index] = Buffer_Recv_Res[jPoint];
3292  jPoint++;
3293  }
3294 
3295  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
3296 
3297  jPoint = (iProcessor+1)*nBuffer_Scalar;
3298  }
3299  }
3300  }
3301 
3302  if ((Kind_Solver == DISC_ADJ_EULER) ||
3303  (Kind_Solver == DISC_ADJ_NAVIER_STOKES) ||
3304  (Kind_Solver == DISC_ADJ_RANS) ||
3305  (Kind_Solver == DISC_ADJ_INC_EULER) ||
3306  (Kind_Solver == DISC_ADJ_INC_NAVIER_STOKES) ||
3307  (Kind_Solver == DISC_ADJ_INC_RANS)) {
3308  /*--- Loop over this partition to collect the current variable ---*/
3309 
3310  jPoint = 0;
3311  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
3312 
3313  /*--- Check for halos & write only if requested ---*/
3314 
3315  if (!Local_Halo[iPoint] || Wrt_Halo) {
3316 
3317  /*--- Load buffers with the skin friction, heat transfer, y+ variables. ---*/
3318 
3319  Buffer_Send_Var[jPoint] = solver[ADJFLOW_SOL]->GetNodes()->GetSensitivity(iPoint, 0);
3320  Buffer_Send_Res[jPoint] = solver[ADJFLOW_SOL]->GetNodes()->GetSensitivity(iPoint, 1);
3321  if (nDim == 3)
3322  Buffer_Send_Vol[jPoint] = solver[ADJFLOW_SOL]->GetNodes()->GetSensitivity(iPoint, 2);
3323  jPoint++;
3324  }
3325  }
3326 
3327  /*--- Gather the data on the master node. ---*/
3328 
3329 #ifdef HAVE_MPI
3330  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3331  SU2_MPI::Gather(Buffer_Send_Res, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Res, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3332  if (nDim == 3)
3333  SU2_MPI::Gather(Buffer_Send_Vol, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Vol, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3334 #else
3335  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint];
3336  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Res[iPoint] = Buffer_Send_Res[iPoint];
3337  if (nDim == 3)
3338  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Vol[iPoint] = Buffer_Send_Vol[iPoint];
3339 #endif
3340 
3341  /*--- The master node unpacks and sorts this variable by global index ---*/
3342 
3343  if (rank == MASTER_NODE) {
3344  jPoint = 0; iVar = iVar_SensDim;
3345  for (iProcessor = 0; iProcessor < size; iProcessor++) {
3346  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
3347 
3348  /*--- Get global index, then loop over each variable and store ---*/
3349 
3350  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
3351  Data[iVar+0][iGlobal_Index] = Buffer_Recv_Var[jPoint];
3352  Data[iVar+1][iGlobal_Index] = Buffer_Recv_Res[jPoint];
3353  if (nDim == 3)
3354  Data[iVar+2][iGlobal_Index] = Buffer_Recv_Vol[jPoint];
3355  jPoint++;
3356  }
3357 
3358  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
3359 
3360  jPoint = (iProcessor+1)*nBuffer_Scalar;
3361  }
3362  }
3363  }
3364 
3365 
3366  /*--- Communicate the Velocities for dynamic FEM problem ---*/
3367 
3368  if ((Kind_Solver == FEM_ELASTICITY) && (config->GetTime_Domain())) {
3369 
3370  /*--- Loop over this partition to collect the current variable ---*/
3371 
3372  jPoint = 0; su2double *Node_Vel;
3373  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
3374 
3375  /*--- Check for halos & write only if requested ---*/
3376 
3377  if (!Local_Halo[iPoint] || Wrt_Halo) {
3378 
3379  /*--- Load buffers with the three grid velocity components. ---*/
3380 
3381  Node_Vel = solver[FEA_SOL]->GetNodes()->GetSolution_Vel(iPoint);
3382  Buffer_Send_Var[jPoint] = Node_Vel[0];
3383  Buffer_Send_Res[jPoint] = Node_Vel[1];
3384  if (geometry->GetnDim() == 3) Buffer_Send_Vol[jPoint] = Node_Vel[2];
3385  jPoint++;
3386  }
3387  }
3388 
3389  /*--- Gather the data on the master node. ---*/
3390 
3391 #ifdef HAVE_MPI
3392  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3393  SU2_MPI::Gather(Buffer_Send_Res, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Res, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3394  if (geometry->GetnDim() == 3) {
3395  SU2_MPI::Gather(Buffer_Send_Vol, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Vol, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3396  }
3397 #else
3398  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint];
3399  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Res[iPoint] = Buffer_Send_Res[iPoint];
3400  if (geometry->GetnDim() == 3) {
3401  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Vol[iPoint] = Buffer_Send_Vol[iPoint];
3402  }
3403 #endif
3404 
3405  /*--- The master node unpacks and sorts this variable by global index ---*/
3406 
3407  if (rank == MASTER_NODE) {
3408  jPoint = 0; iVar = iVar_FEA_Vel;
3409  for (iProcessor = 0; iProcessor < size; iProcessor++) {
3410  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
3411 
3412  /*--- Get global index, then loop over each variable and store ---*/
3413 
3414  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
3415  Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint];
3416  Data[iVar+1][iGlobal_Index] = Buffer_Recv_Res[jPoint];
3417  if (geometry->GetnDim() == 3)
3418  Data[iVar+2][iGlobal_Index] = Buffer_Recv_Vol[jPoint];
3419  jPoint++;
3420  }
3421 
3422  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
3423 
3424  jPoint = (iProcessor+1)*nBuffer_Scalar;
3425  }
3426  }
3427  }
3428 
3429  /*--- Communicate the Accelerations for dynamic FEM problem ---*/
3430 
3431  if ((Kind_Solver == FEM_ELASTICITY) && (config->GetTime_Domain())) {
3432 
3433  /*--- Loop over this partition to collect the current variable ---*/
3434 
3435  jPoint = 0; su2double *Node_Accel;
3436  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
3437 
3438  /*--- Check for halos & write only if requested ---*/
3439 
3440  if (!Local_Halo[iPoint] || Wrt_Halo) {
3441 
3442  /*--- Load buffers with the three grid velocity components. ---*/
3443 
3444  Node_Accel = solver[FEA_SOL]->GetNodes()->GetSolution_Accel(iPoint);
3445  Buffer_Send_Var[jPoint] = Node_Accel[0];
3446  Buffer_Send_Res[jPoint] = Node_Accel[1];
3447  if (geometry->GetnDim() == 3) Buffer_Send_Vol[jPoint] = Node_Accel[2];
3448  jPoint++;
3449  }
3450  }
3451 
3452  /*--- Gather the data on the master node. ---*/
3453 
3454 #ifdef HAVE_MPI
3455  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3456  SU2_MPI::Gather(Buffer_Send_Res, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Res, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3457  if (geometry->GetnDim() == 3) {
3458  SU2_MPI::Gather(Buffer_Send_Vol, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Vol, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3459  }
3460 #else
3461  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint];
3462  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Res[iPoint] = Buffer_Send_Res[iPoint];
3463  if (geometry->GetnDim() == 3) {
3464  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Vol[iPoint] = Buffer_Send_Vol[iPoint];
3465  }
3466 #endif
3467 
3468  /*--- The master node unpacks and sorts this variable by global index ---*/
3469 
3470  if (rank == MASTER_NODE) {
3471  jPoint = 0; iVar = iVar_FEA_Accel;
3472  for (iProcessor = 0; iProcessor < size; iProcessor++) {
3473  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
3474 
3475  /*--- Get global index, then loop over each variable and store ---*/
3476 
3477  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
3478  Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint];
3479  Data[iVar+1][iGlobal_Index] = Buffer_Recv_Res[jPoint];
3480  if (geometry->GetnDim() == 3)
3481  Data[iVar+2][iGlobal_Index] = Buffer_Recv_Vol[jPoint];
3482  jPoint++;
3483  }
3484 
3485  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
3486 
3487  jPoint = (iProcessor+1)*nBuffer_Scalar;
3488  }
3489  }
3490  }
3491 
3492  /*--- Communicate the FEM elasticity stresses (2D) - New elasticity solver---*/
3493 
3494  if (Kind_Solver == FEM_ELASTICITY) {
3495 
3496  /*--- Loop over this partition to collect the current variable ---*/
3497 
3498  jPoint = 0; su2double *Stress;
3499  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
3500 
3501  /*--- Check for halos & write only if requested ---*/
3502 
3503  if (!Local_Halo[iPoint] || Wrt_Halo) {
3504 
3505  /*--- Load buffers with the three grid velocity components. ---*/
3506 
3507  Stress = solver[FEA_SOL]->GetNodes()->GetStress_FEM(iPoint);
3508  /*--- Sigma xx ---*/
3509  Buffer_Send_Var[jPoint] = Stress[0];
3510  /*--- Sigma yy ---*/
3511  Buffer_Send_Res[jPoint] = Stress[1];
3512  /*--- Sigma xy ---*/
3513  Buffer_Send_Vol[jPoint] = Stress[2];
3514  jPoint++;
3515  }
3516  }
3517 
3518  /*--- Gather the data on the master node. ---*/
3519 
3520 #ifdef HAVE_MPI
3521  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3522  SU2_MPI::Gather(Buffer_Send_Res, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Res, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3523  SU2_MPI::Gather(Buffer_Send_Vol, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Vol, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3524 #else
3525  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint];
3526  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Res[iPoint] = Buffer_Send_Res[iPoint];
3527  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Vol[iPoint] = Buffer_Send_Vol[iPoint];
3528 #endif
3529 
3530  /*--- The master node unpacks and sorts this variable by global index ---*/
3531 
3532  if (rank == MASTER_NODE) {
3533  jPoint = 0; iVar = iVar_FEA_Stress;
3534  for (iProcessor = 0; iProcessor < size; iProcessor++) {
3535  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
3536 
3537  /*--- Get global index, then loop over each variable and store ---*/
3538 
3539  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
3540  Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint];
3541  Data[iVar+1][iGlobal_Index] = Buffer_Recv_Res[jPoint];
3542  Data[iVar+2][iGlobal_Index] = Buffer_Recv_Vol[jPoint];
3543  jPoint++;
3544  }
3545 
3546  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
3547 
3548  jPoint = (iProcessor+1)*nBuffer_Scalar;
3549  }
3550  }
3551  }
3552 
3553  /*--- Communicate the FEM elasticity stresses (3D) - New elasticity solver---*/
3554 
3555  if ((Kind_Solver == FEM_ELASTICITY) && (geometry->GetnDim() == 3)) {
3556 
3557  /*--- Loop over this partition to collect the current variable ---*/
3558 
3559  jPoint = 0; su2double *Stress;
3560  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
3561 
3562  /*--- Check for halos & write only if requested ---*/
3563 
3564  if (!Local_Halo[iPoint] || Wrt_Halo) {
3565 
3566  /*--- Load buffers with the three grid velocity components. ---*/
3567 
3568  Stress = solver[FEA_SOL]->GetNodes()->GetStress_FEM(iPoint);
3569  /*--- Sigma zz ---*/
3570  Buffer_Send_Var[jPoint] = Stress[3];
3571  /*--- Sigma xz ---*/
3572  Buffer_Send_Res[jPoint] = Stress[4];
3573  /*--- Sigma yz ---*/
3574  Buffer_Send_Vol[jPoint] = Stress[5];
3575  jPoint++;
3576  }
3577  }
3578 
3579  /*--- Gather the data on the master node. ---*/
3580 
3581 #ifdef HAVE_MPI
3582  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3583  SU2_MPI::Gather(Buffer_Send_Res, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Res, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3584  SU2_MPI::Gather(Buffer_Send_Vol, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Vol, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3585 #else
3586  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint];
3587  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Res[iPoint] = Buffer_Send_Res[iPoint];
3588  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Vol[iPoint] = Buffer_Send_Vol[iPoint];
3589 
3590 #endif
3591 
3592  /*--- The master node unpacks and sorts this variable by global index ---*/
3593 
3594  if (rank == MASTER_NODE) {
3595  jPoint = 0; iVar = iVar_FEA_Stress_3D;
3596  for (iProcessor = 0; iProcessor < size; iProcessor++) {
3597  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
3598 
3599  /*--- Get global index, then loop over each variable and store ---*/
3600 
3601  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
3602  Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint];
3603  Data[iVar+1][iGlobal_Index] = Buffer_Recv_Res[jPoint];
3604  Data[iVar+2][iGlobal_Index] = Buffer_Recv_Vol[jPoint];
3605  jPoint++;
3606  }
3607 
3608  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
3609 
3610  jPoint = (iProcessor+1)*nBuffer_Scalar;
3611  }
3612  }
3613  }
3614 
3615 
3616  /*--- Communicate the Linear elasticity ---*/
3617 
3618  if ( Kind_Solver == FEM_ELASTICITY ) {
3619 
3620  /*--- Loop over this partition to collect the current variable ---*/
3621  jPoint = 0;
3622  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
3623 
3624  /*--- Check for halos & write only if requested ---*/
3625 
3626  if (!Local_Halo[iPoint] || Wrt_Halo) {
3627 
3628  /*--- Load buffers with the temperature and laminar viscosity variables. ---*/
3629 
3630  Buffer_Send_Var[jPoint] = solver[FEA_SOL]->GetNodes()->GetVonMises_Stress(iPoint);
3631  jPoint++;
3632  }
3633  }
3634 
3635  /*--- Gather the data on the master node. ---*/
3636 
3637 #ifdef HAVE_MPI
3638  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3639 #else
3640  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint];
3641 #endif
3642 
3643  /*--- The master node unpacks and sorts this variable by global index ---*/
3644 
3645  if (rank == MASTER_NODE) {
3646  jPoint = 0; iVar = iVar_FEA_Extra;
3647  for (iProcessor = 0; iProcessor < size; iProcessor++) {
3648  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
3649 
3650  /*--- Get global index, then loop over each variable and store ---*/
3651 
3652  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
3653  Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint];
3654  jPoint++;
3655  }
3656 
3657  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
3658 
3659  jPoint = (iProcessor+1)*nBuffer_Scalar;
3660  }
3661  }
3662  }
3663 
3664  if ((Kind_Solver == DISC_ADJ_FEM) && (config->GetFSI_Simulation())) {
3665  /*--- Loop over this partition to collect the current variable ---*/
3666 
3667  jPoint = 0;
3668  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
3669 
3670  /*--- Check for halos & write only if requested ---*/
3671 
3672  if (!Local_Halo[iPoint] || Wrt_Halo) {
3673 
3674  /*--- Load buffers with the skin friction, heat transfer, y+ variables. ---*/
3675 
3676  Buffer_Send_Var[jPoint] = solver[ADJFEA_SOL]->GetNodes()->GetGeometry_CrossTerm_Derivative(iPoint, 0);
3677  Buffer_Send_Res[jPoint] = solver[ADJFEA_SOL]->GetNodes()->GetGeometry_CrossTerm_Derivative(iPoint, 1);
3678  if (geometry->GetnDim() == 3)
3679  Buffer_Send_Vol[jPoint] = solver[ADJFEA_SOL]->GetNodes()->GetGeometry_CrossTerm_Derivative(iPoint, 2);
3680  jPoint++;
3681  }
3682  }
3683 
3684  /*--- Gather the data on the master node. ---*/
3685 
3686 #ifdef HAVE_MPI
3687  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3688  SU2_MPI::Gather(Buffer_Send_Res, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Res, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3689  if (nDim == 3)
3690  SU2_MPI::Gather(Buffer_Send_Vol, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Vol, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3691 #else
3692  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint];
3693  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Res[iPoint] = Buffer_Send_Res[iPoint];
3694  if (nDim == 3)
3695  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Vol[iPoint] = Buffer_Send_Vol[iPoint];
3696 #endif
3697 
3698  /*--- The master node unpacks and sorts this variable by global index ---*/
3699 
3700  if (rank == MASTER_NODE) {
3701  jPoint = 0; iVar = iVar_FEA_Extra;
3702  for (iProcessor = 0; iProcessor < size; iProcessor++) {
3703  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
3704 
3705  /*--- Get global index, then loop over each variable and store ---*/
3706 
3707  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
3708  Data[iVar+0][iGlobal_Index] = Buffer_Recv_Var[jPoint];
3709  Data[iVar+1][iGlobal_Index] = Buffer_Recv_Res[jPoint];
3710  if (nDim == 3)
3711  Data[iVar+2][iGlobal_Index] = Buffer_Recv_Vol[jPoint];
3712  jPoint++;
3713  }
3714 
3715  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
3716 
3717  jPoint = (iProcessor+1)*nBuffer_Scalar;
3718  }
3719  }
3720  }
3721 
3722  if (config->GetExtraOutput()) {
3723 
3724  for (jVar = 0; jVar < nVar_Extra; jVar++) {
3725 
3726  /*--- Loop over this partition to collect the current variable ---*/
3727 
3728  jPoint = 0;
3729  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
3730 
3731  /*--- Check for halos & write only if requested ---*/
3732 
3733  if (!Local_Halo[iPoint] || Wrt_Halo) {
3734 
3735  /*--- Get this variable into the temporary send buffer. ---*/
3736 
3737  if (Kind_Solver == RANS) {
3738  Buffer_Send_Var[jPoint] = solver[TURB_SOL]->OutputVariables[iPoint*nVar_Extra+jVar];
3739  }
3740  jPoint++;
3741 
3742  }
3743  }
3744 
3745  /*--- Gather the data on the master node. ---*/
3746 
3747 #ifdef HAVE_MPI
3748  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3749 #else
3750  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint];
3751 #endif
3752 
3753  /*--- The master node unpacks and sorts this variable by global index ---*/
3754 
3755  if (rank == MASTER_NODE) {
3756  jPoint = 0; iVar = iVar_Extra;
3757  for (iProcessor = 0; iProcessor < size; iProcessor++) {
3758  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
3759 
3760  /*--- Get global index, then loop over each variable and store ---*/
3761 
3762  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
3763  Data[iVar+jVar][iGlobal_Index] = Buffer_Recv_Var[jPoint];
3764  jPoint++;
3765  }
3766 
3767  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
3768 
3769  jPoint = (iProcessor+1)*nBuffer_Scalar;
3770  }
3771  }
3772  }
3773  }
3774 
3775 
3776 
3777  /*--- Immediately release the temporary buffers. ---*/
3778 
3779  delete [] Buffer_Send_Var;
3780  delete [] Buffer_Send_Res;
3781  delete [] Buffer_Send_Vol;
3782  delete [] Buffer_Send_GlobalIndex;
3783  if (rank == MASTER_NODE) {
3784  delete [] Buffer_Recv_nPoint;
3785  delete [] Buffer_Recv_Var;
3786  delete [] Buffer_Recv_Res;
3787  delete [] Buffer_Recv_Vol;
3788  delete [] Buffer_Recv_GlobalIndex;
3789  }
3790 
3791  /*--- Release memory needed for surface coefficients ---*/
3792 
3793  delete [] Local_Halo;
3794 
3795  if (((Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) ||
3796  ((Kind_Solver == INC_NAVIER_STOKES) || (Kind_Solver == INC_RANS)) ||
3797  ((Kind_Solver == FEM_NAVIER_STOKES) || (Kind_Solver == FEM_RANS) || (Kind_Solver == FEM_LES))) {
3798  delete[] Aux_Frict_x; delete[] Aux_Frict_y; delete[] Aux_Frict_z;
3799  delete [] Aux_Heat; delete [] Aux_yPlus;
3800  }
3801  if (( Kind_Solver == ADJ_EULER ) ||
3802  ( Kind_Solver == ADJ_NAVIER_STOKES ) ||
3803  ( Kind_Solver == ADJ_RANS ) ||
3804  ( Kind_Solver == DISC_ADJ_EULER ) ||
3805  ( Kind_Solver == DISC_ADJ_NAVIER_STOKES ) ||
3806  ( Kind_Solver == DISC_ADJ_RANS ) ||
3807  ( Kind_Solver == DISC_ADJ_INC_EULER ) ||
3808  ( Kind_Solver == DISC_ADJ_INC_NAVIER_STOKES ) ||
3809  ( Kind_Solver == DISC_ADJ_INC_RANS )) {
3810  delete [] Aux_Sens;
3811  }
3812 
3813 }
3814 
3815 void COutputLegacy::MergeBaselineSolution(CConfig *config, CGeometry *geometry, CSolver *solver, unsigned short val_iZone) {
3816 
3817  /*--- Local variables needed on all processors ---*/
3818  unsigned short iVar;
3819  unsigned long iPoint = 0, jPoint = 0;
3820 
3821  nVar_Total = config->fields.size() - 1;
3822 
3823  /*--- Merge the solution either in serial or parallel. ---*/
3824 
3825 #ifndef HAVE_MPI
3826 
3827  /*--- In serial, the single process has access to all solution data,
3828  so it is simple to retrieve and store inside Solution_Data. ---*/
3829 
3830  unsigned short iMarker;
3831  unsigned long iVertex, nTotalPoints = 0;
3832  int SendRecv;
3833 
3834  /*--- First, create a structure to locate any periodic halo nodes ---*/
3835  int *Local_Halo = new int[geometry->GetnPoint()];
3836  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
3837  Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain();
3838 
3839  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
3840  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
3841  SendRecv = config->GetMarker_All_SendRecv(iMarker);
3842  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
3843  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
3844  if ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
3845  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1) &&
3846  (SendRecv < 0)) {
3847  Local_Halo[iPoint] = false;
3848  }
3849  }
3850 
3851  }
3852  }
3853 
3854  /*--- Total number of points in the mesh (this might include periodic points). ---*/
3855 
3856  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
3857  if (!Local_Halo[iPoint]) nTotalPoints++;
3858 
3859  nGlobal_Poin = nTotalPoints;
3860  Data = new su2double*[nVar_Total];
3861  for (iVar = 0; iVar < nVar_Total; iVar++) {
3862  Data[iVar] = new su2double[nGlobal_Poin];
3863  }
3864 
3865  /*--- Loop over all points in the mesh, but only write data
3866  for nodes in the domain (ignore periodic halo nodes). ---*/
3867 
3868  jPoint = 0;
3869  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
3870  if (!Local_Halo[iPoint]) {
3871 
3872  /*--- Solution (first, and second system of equations) ---*/
3873 
3874  unsigned short jVar = 0;
3875  for (iVar = 0; iVar < nVar_Total; iVar++) {
3876  Data[jVar][jPoint] = solver->GetNodes()->GetSolution(iPoint,iVar);
3877  jVar++;
3878  }
3879  }
3880 
3881  /*--- Increment jPoint as the counter. We need this because iPoint
3882  may include halo nodes that we skip over during this loop. ---*/
3883 
3884  jPoint++;
3885 
3886  }
3887 
3888 #else
3889 
3890  /*--- MPI preprocessing ---*/
3891 
3892  int nProcessor = size, iProcessor;
3893 
3894  /*--- Local variables needed for merging with MPI ---*/
3895 
3896  unsigned long iVertex, iMarker;
3897  unsigned long Buffer_Send_nPoint[1], *Buffer_Recv_nPoint = NULL;
3898  unsigned long nLocalPoint = 0, MaxLocalPoint = 0;
3899  unsigned long iGlobal_Index = 0, nBuffer_Scalar = 0;
3900 
3901  int *Local_Halo = new int[geometry->GetnPoint()];
3902  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
3903  Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain();
3904 
3905  bool Wrt_Halo = config->GetWrt_Halo(), isPeriodic;
3906 
3907  /*--- Search all send/recv boundaries on this partition for any periodic
3908  nodes that were part of the original domain. We want to recover these
3909  for visualization purposes. ---*/
3910 
3911  if (Wrt_Halo) {
3912  nLocalPoint = geometry->GetnPoint();
3913  } else {
3914  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
3915  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
3916 
3917  /*--- Checking for less than or equal to the rank, because there may
3918  be some periodic halo nodes that send info to the same rank. ---*/
3919 
3920  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
3921  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
3922  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
3923  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1));
3924  if (isPeriodic) Local_Halo[iPoint] = false;
3925  }
3926  }
3927  }
3928 
3929  /*--- Sum total number of nodes that belong to the domain ---*/
3930 
3931  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
3932  if (Local_Halo[iPoint] == false)
3933  nLocalPoint++;
3934 
3935  }
3936  Buffer_Send_nPoint[0] = nLocalPoint;
3937 
3938  if (rank == MASTER_NODE) Buffer_Recv_nPoint = new unsigned long[nProcessor];
3939 
3940  SU2_MPI::Allreduce(&nLocalPoint, &MaxLocalPoint, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
3941  SU2_MPI::Gather(&Buffer_Send_nPoint, 1, MPI_UNSIGNED_LONG, Buffer_Recv_nPoint, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
3942 
3943  nBuffer_Scalar = MaxLocalPoint;
3944 
3945  /*--- Send and Recv buffers. ---*/
3946 
3947  su2double *Buffer_Send_Var = new su2double[MaxLocalPoint];
3948  su2double *Buffer_Recv_Var = NULL;
3949 
3950  unsigned long *Buffer_Send_GlobalIndex = new unsigned long[MaxLocalPoint];
3951  unsigned long *Buffer_Recv_GlobalIndex = NULL;
3952 
3953  /*--- Prepare the receive buffers in the master node only. ---*/
3954  if (rank == MASTER_NODE) {
3955 
3956  Buffer_Recv_Var = new su2double[nProcessor*MaxLocalPoint];
3957  Buffer_Recv_GlobalIndex = new unsigned long[nProcessor*MaxLocalPoint];
3958 
3959  /*--- Sum total number of nodes to be written and allocate arrays ---*/
3960  nGlobal_Poin = 0;
3961  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
3962  nGlobal_Poin += Buffer_Recv_nPoint[iProcessor];
3963  }
3964  Data = new su2double*[nVar_Total];
3965  for (iVar = 0; iVar < nVar_Total; iVar++) {
3966  Data[iVar] = new su2double[nGlobal_Poin];
3967  }
3968 
3969  }
3970 
3971  /*--- Main communication routine. Loop over each variable that has
3972  been requested by the user and perform the MPI comm. Temporary
3973  1-D buffers are used to send the solution for each variable at all
3974  nodes on each partition to the master node. These are then unpacked
3975  by the master and sorted by global index in one large n-dim. array. ---*/
3976 
3977  for (iVar = 0; iVar < nVar_Total; iVar++) {
3978 
3979  /*--- Loop over this partition to collect the current variable ---*/
3980  jPoint = 0;
3981  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
3982 
3983  /*--- Check for halos and write only if requested ---*/
3984  if (!Local_Halo[iPoint] || Wrt_Halo) {
3985 
3986  /*--- Get this variable into the temporary send buffer. ---*/
3987  Buffer_Send_Var[jPoint] = solver->GetNodes()->GetSolution(iPoint,iVar);
3988 
3989  /*--- Only send/recv the volumes & global indices during the first loop ---*/
3990  if (iVar == 0) {
3991  Buffer_Send_GlobalIndex[jPoint] = geometry->node[iPoint]->GetGlobalIndex();
3992  }
3993  jPoint++;
3994  }
3995  }
3996 
3997  /*--- Gather the data on the master node. ---*/
3998 
3999  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
4000  if (iVar == 0) {
4001  SU2_MPI::Gather(Buffer_Send_GlobalIndex, nBuffer_Scalar, MPI_UNSIGNED_LONG, Buffer_Recv_GlobalIndex, nBuffer_Scalar, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
4002  }
4003 
4004  /*--- The master node unpacks and sorts this variable by global index ---*/
4005  if (rank == MASTER_NODE) {
4006  jPoint = 0;
4007  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
4008  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
4009 
4010  /*--- Get global index, then loop over each variable and store ---*/
4011  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
4012  Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint];
4013  jPoint++;
4014  }
4015  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
4016  jPoint = (iProcessor+1)*nBuffer_Scalar;
4017  }
4018  }
4019  }
4020 
4021  /*--- Immediately release the temporary buffers. ---*/
4022 
4023  delete [] Buffer_Send_Var;
4024  delete [] Buffer_Send_GlobalIndex;
4025  if (rank == MASTER_NODE) {
4026  delete [] Buffer_Recv_Var;
4027  delete [] Buffer_Recv_GlobalIndex;
4028  }
4029 
4030 #endif
4031 
4032  delete [] Local_Halo;
4033 
4034 }
4035 
4036 void COutputLegacy::SetRestart(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone) {
4037 
4038  /*--- Local variables ---*/
4039 
4040  unsigned short nZone = geometry->GetnZone();
4041  unsigned short Kind_Solver = config->GetKind_Solver();
4042  unsigned short iVar, iDim, nDim = geometry->GetnDim();
4043  unsigned long iPoint, iExtIter = config->GetInnerIter();
4044  bool dynamic_grid = config->GetDynamic_Grid();
4045  bool dynamic_fem = (config->GetTime_Domain());
4046  bool fem = (config->GetKind_Solver() == FEM_ELASTICITY);
4047  bool disc_adj_fem = (config->GetKind_Solver() == DISC_ADJ_FEM);
4048  ofstream restart_file;
4049  ofstream meta_file;
4050  string filename, meta_filename;
4051  bool adjoint = config->GetContinuous_Adjoint() || config->GetDiscrete_Adjoint();
4052 
4053  /*--- Retrieve filename from config ---*/
4054 
4055 // if (((config->GetContinuous_Adjoint()) || (config->GetDiscrete_Adjoint())) && ((config->GetKind_Solver() != DISC_ADJ_FEM))) {
4056 // filename = config->GetRestart_AdjFileName();
4057 // filename = config->GetObjFunc_Extension(filename);
4058 // } else if (fem) {
4059 // filename = config->GetRestart_FEMFileName();
4060 // } else if (disc_adj_fem){
4061 // filename = config->GetRestart_AdjFEMFileName();
4062 // } else {
4063 // filename = config->GetRestart_FileName();
4064 // }
4065 
4066  /*--- Append the zone number if multizone problems ---*/
4067  if (nZone > 1)
4068  filename= config->GetMultizone_FileName(filename, val_iZone, ".dat");
4069 
4070  /*--- Unsteady problems require an iteration number to be appended. ---*/
4071  if (config->GetTime_Marching() == HARMONIC_BALANCE) {
4072  filename = config->GetUnsteady_FileName(filename, SU2_TYPE::Int(config->GetiInst()), ".dat");
4073  } else if (config->GetTime_Domain()) {
4074  filename = config->GetUnsteady_FileName(filename, SU2_TYPE::Int(iExtIter), ".dat");
4075  } else if ((fem || disc_adj_fem) && (config->GetWrt_Dynamic())) {
4076  filename = config->GetUnsteady_FileName(filename, SU2_TYPE::Int(iExtIter), ".dat");
4077  }
4078 
4079  /*--- Open the restart file and write the solution. ---*/
4080 
4081  restart_file.open(filename.c_str(), ios::out);
4082  restart_file.precision(15);
4083 
4084  /*--- Write the header line based on the particular solver ----*/
4085 
4086  restart_file << "\"PointID\"";
4087 
4088  /*--- Mesh coordinates are always written to the restart first ---*/
4089 
4090  if (nDim == 2) {
4091  restart_file << "\t\"x\"\t\"y\"";
4092  } else {
4093  restart_file << "\t\"x\"\t\"y\"\t\"z\"";
4094  }
4095 
4096  for (iVar = 0; iVar < nVar_Consv; iVar++) {
4097  if (( Kind_Solver == FEM_ELASTICITY ) || ( Kind_Solver == DISC_ADJ_FEM))
4098  restart_file << "\t\"Displacement_" << iVar+1<<"\"";
4099  else
4100  restart_file << "\t\"Conservative_" << iVar+1<<"\"";
4101  }
4102 
4103  if (config->GetWrt_Limiters()) {
4104  for (iVar = 0; iVar < nVar_Consv; iVar++) {
4105  restart_file << "\t\"Limiter_" << iVar+1<<"\"";
4106  }
4107  }
4108  if (config->GetWrt_Residuals()) {
4109  for (iVar = 0; iVar < nVar_Consv; iVar++) {
4110  restart_file << "\t\"Residual_" << iVar+1<<"\"";
4111  }
4112  }
4113 
4114  /*--- Mesh velocities for dynamic mesh cases ---*/
4115 
4116  if (dynamic_grid && !fem) {
4117  if (nDim == 2) {
4118  restart_file << "\t\"Grid_Velx\"\t\"Grid_Vely\"";
4119  } else {
4120  restart_file << "\t\"Grid_Velx\"\t\"Grid_Vely\"\t\"Grid_Velz\"";
4121  }
4122  }
4123 
4124  if ((Kind_Solver == EULER) || (Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS) ||
4125  (Kind_Solver == INC_EULER) || (Kind_Solver == INC_NAVIER_STOKES) || (Kind_Solver == INC_RANS)) {
4126  if (config->GetTabular_FileFormat() == TAB_CSV) {
4127  restart_file << "\t\"Pressure\"\t\"Temperature\"\t\"Pressure_Coefficient\"\t\"Mach\"";
4128  } else
4129  restart_file << "\t\"Pressure\"\t\"Temperature\"\t\"C<sub>p</sub>\"\t\"Mach\"";
4130  }
4131 
4132  if ((Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS) ||
4133  (Kind_Solver == INC_NAVIER_STOKES) || (Kind_Solver == INC_RANS)) {
4134  if (config->GetTabular_FileFormat() == TAB_CSV) {
4135  if (nDim == 2) restart_file << "\t\"Laminar_Viscosity\"\t\"Skin_Friction_Coefficient_X\"\t\"Skin_Friction_Coefficient_Y\"\t\"Heat_Flux\"\t\"Y_Plus\"";
4136  if (nDim == 3) restart_file << "\t\"Laminar_Viscosity\"\t\"Skin_Friction_Coefficient_X\"\t\"Skin_Friction_Coefficient_Y\"\t\"Skin_Friction_Coefficient_Z\"\t\"Heat_Flux\"\t\"Y_Plus\"";
4137  } else {
4138  if (nDim == 2) restart_file << "\t\"<greek>m</greek>\"\t\"C<sub>f</sub>_x\"\t\"C<sub>f</sub>_y\"\t\"h\"\t\"y<sup>+</sup>\"";
4139  if (nDim == 3) restart_file << "\t\"<greek>m</greek>\"\t\"C<sub>f</sub>_x\"\t\"C<sub>f</sub>_y\"\t\"C<sub>f</sub>_z\"\t\"h\"\t\"y<sup>+</sup>\"";
4140  }
4141  }
4142 
4143  if (Kind_Solver == RANS || Kind_Solver == INC_RANS) {
4144  if ((config->GetTabular_FileFormat() == TAB_CSV)) {
4145  restart_file << "\t\"Eddy_Viscosity\"";
4146  } else
4147  restart_file << "\t\"<greek>m</greek><sub>t</sub>\"";
4148  }
4149 
4150  if (config->GetWrt_SharpEdges()) {
4151  if (((Kind_Solver == EULER) || (Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) ||
4152  ((Kind_Solver == INC_EULER) || (Kind_Solver == INC_NAVIER_STOKES) || (Kind_Solver == INC_RANS))) {
4153  restart_file << "\t\"Sharp_Edge_Dist\"";
4154  }
4155  }
4156 
4157  if ((Kind_Solver == ADJ_EULER ) ||
4158  (Kind_Solver == ADJ_NAVIER_STOKES ) ||
4159  (Kind_Solver == ADJ_RANS ) ) {
4160  restart_file << "\t\"Surface_Sensitivity\"\t\"Solution_Sensor\"";
4161  }
4162  if (( Kind_Solver == DISC_ADJ_EULER ) ||
4163  ( Kind_Solver == DISC_ADJ_NAVIER_STOKES ) ||
4164  ( Kind_Solver == DISC_ADJ_RANS ) ||
4165  ( Kind_Solver == DISC_ADJ_INC_EULER ) ||
4166  ( Kind_Solver == DISC_ADJ_INC_NAVIER_STOKES ) ||
4167  ( Kind_Solver == DISC_ADJ_INC_RANS )) {
4168  restart_file << "\t\"Surface_Sensitivity\"\t\"Sensitivity_x\"\t\"Sensitivity_y\"";
4169  if (geometry->GetnDim() == 3) {
4170  restart_file << "\t\"Sensitivity_z\"";
4171  }
4172  }
4173 
4174  if (Kind_Solver == FEM_ELASTICITY) {
4175  if (!dynamic_fem) {
4176  if (geometry->GetnDim() == 2)
4177  restart_file << "\t\"Sxx\"\t\"Syy\"\t\"Sxy\"\t\"Von_Mises_Stress\"";
4178  if (geometry->GetnDim() == 3)
4179  restart_file << "\t\"Sxx\"\t\"Syy\"\t\"Sxy\"\t\"Szz\"\t\"Sxz\"\t\"Syz\"\t\"Von_Mises_Stress\"";
4180  }
4181  else if (dynamic_fem) {
4182  if (geometry->GetnDim() == 2) {
4183  restart_file << "\t\"Velocity_1\"\t\"Velocity_2\"\t\"Acceleration_1\"\t\"Acceleration_2\"";
4184  restart_file << "\t\"Sxx\"\t\"Syy\"\t\"Sxy\"\t\"Von_Mises_Stress\"";
4185  }
4186  if (geometry->GetnDim() == 3) {
4187  restart_file << "\t\"Velocity_1\"\t\"Velocity_2\"\t\"Velocity_3\"\t\"Acceleration_1\"\t\"Acceleration_2\"\t\"Acceleration_3\"";
4188  restart_file << "\t\"Sxx\"\t\"Syy\"\t\"Sxy\"\t\"Szz\"\t\"Sxz\"\t\"Syz\"\t\"Von_Mises_Stress\"";
4189  }
4190  }
4191  }
4192 
4193  if ((Kind_Solver == DISC_ADJ_FEM) && (config->GetFSI_Simulation())){
4194  if (geometry->GetnDim() == 2)
4195  restart_file << "\t\"CrossTerm_1\"\t\"CrossTerm_2\"";
4196  if (geometry->GetnDim() == 3)
4197  restart_file << "\t\"CrossTerm_1\"\t\"CrossTerm_2\"\t\"CrossTerm_3\"";
4198  }
4199 
4200 
4201  if (config->GetExtraOutput()) {
4202  string *headings = NULL;
4203  //if (Kind_Solver == RANS) {
4204  headings = solver[TURB_SOL]->OutputHeadingNames;
4205  //}
4206 
4207  for (iVar = 0; iVar < nVar_Extra; iVar++) {
4208  if (headings == NULL) {
4209  restart_file << "\t\"ExtraOutput_" << iVar+1<<"\"";
4210  } else {
4211  restart_file << "\t\""<< headings[iVar] <<"\"";
4212  }
4213  }
4214  }
4215 
4216 
4217  restart_file << "\n";
4218 
4219  /*--- Write the restart file ---*/
4220 
4221  /*--- Determine whether or not the FEM solver is used, which decides the
4222  type of geometry classes that are instantiated. ---*/
4223  bool fem_solver = ((config->GetKind_Solver() == FEM_EULER) ||
4224  (config->GetKind_Solver() == FEM_NAVIER_STOKES) ||
4225  (config->GetKind_Solver() == FEM_RANS) ||
4226  (config->GetKind_Solver() == FEM_LES));
4227 
4228  unsigned long nPointTotal = 0;
4229  if ( fem_solver ) {
4230  nPointTotal = solver[FLOW_SOL]->GetnDOFsGlobal();
4231  } else {
4232  nPointTotal = geometry->GetGlobal_nPointDomain();
4233  }
4234 
4235  for (iPoint = 0; iPoint < nPointTotal; iPoint++) {
4236 
4237  /*--- Index of the point ---*/
4238  restart_file << iPoint << "\t";
4239 
4240  /*--- Write the grid coordinates first ---*/
4241  for (iDim = 0; iDim < nDim; iDim++) {
4242  restart_file << scientific << Coords[iDim][iPoint] << "\t";
4243  }
4244 
4245  /*--- Loop over the variables and write the values to file ---*/
4246  for (iVar = 0; iVar < nVar_Total; iVar++) {
4247  restart_file << scientific << Data[iVar][iPoint] << "\t";
4248  }
4249  restart_file << "\n";
4250  }
4251 
4252  /*--- Write the general header and flow conditions ----*/
4253 
4254 // if (dual_time)
4255  restart_file <<"EXT_ITER= " << config->GetInnerIter() + 1 << endl;
4256 // else
4257 // restart_file <<"EXT_ITER= " << config->GetInnerIter() + config->GetInnerIter_OffSet() + 1 << endl;
4258  restart_file <<"AOA= " << config->GetAoA() - config->GetAoA_Offset() << endl;
4259  restart_file <<"SIDESLIP_ANGLE= " << config->GetAoS() - config->GetAoS_Offset() << endl;
4260  restart_file <<"INITIAL_BCTHRUST= " << config->GetInitial_BCThrust() << endl;
4261  restart_file <<"DCD_DCL_VALUE= " << config->GetdCD_dCL() << endl;
4262  restart_file <<"DCMX_DCL_VALUE= " << config->GetdCMx_dCL() << endl;
4263  restart_file <<"DCMY_DCL_VALUE= " << config->GetdCMy_dCL() << endl;
4264  restart_file <<"DCMZ_DCL_VALUE= " << config->GetdCMz_dCL() << endl;
4265  if (adjoint) restart_file << "SENS_AOA=" << solver[ADJFLOW_SOL]->GetTotal_Sens_AoA() * PI_NUMBER / 180.0 << endl;
4266 
4267  /*--- Close the data portion of the restart file. ---*/
4268 
4269  restart_file.close();
4270 
4271 }
4272 
4274 
4275  unsigned short iDim, nDim = geometry->GetnDim();
4276 
4277  /*--- The master node alone owns all data found in this routine. ---*/
4278 
4279  if (rank == MASTER_NODE) {
4280 
4281  /*--- Deallocate memory for coordinate data ---*/
4282 
4283  for (iDim = 0; iDim < nDim; iDim++) {
4284  delete [] Coords[iDim];
4285  }
4286  delete [] Coords;
4287  }
4288 }
4289 
4290 void COutputLegacy::DeallocateConnectivity(CConfig *config, CGeometry *geometry, bool surf_sol) {
4291 
4292  /*--- The master node alone owns all data found in this routine. ---*/
4293  if (rank == MASTER_NODE) {
4294 
4295  /*--- Deallocate memory for connectivity data ---*/
4296  if (surf_sol) {
4297  if (nGlobal_Line > 0 && Conn_Line != NULL) delete [] Conn_Line;
4298  if (nGlobal_BoundTria > 0 && Conn_BoundTria != NULL) delete [] Conn_BoundTria;
4299  if (nGlobal_BoundQuad > 0 && Conn_BoundQuad != NULL) delete [] Conn_BoundQuad;
4300  }
4301  else {
4302  if (nGlobal_Tria > 0 && Conn_Tria != NULL) delete [] Conn_Tria;
4303  if (nGlobal_Quad > 0 && Conn_Quad != NULL) delete [] Conn_Quad;
4304  if (nGlobal_Tetr > 0 && Conn_Tetr != NULL) delete [] Conn_Tetr;
4305  if (nGlobal_Hexa > 0 && Conn_Hexa != NULL) delete [] Conn_Hexa;
4306  if (nGlobal_Pris > 0 && Conn_Pris != NULL) delete [] Conn_Pris;
4307  if (nGlobal_Pyra > 0 && Conn_Pyra != NULL) delete [] Conn_Pyra;
4308 
4309  }
4310 
4311  }
4312 }
4313 
4315 
4316  /*--- The master node alone owns all data found in this routine. ---*/
4317  if (rank == MASTER_NODE) {
4318 
4319  /*--- Deallocate memory for solution data ---*/
4320  for (unsigned short iVar = 0; iVar < nVar_Total; iVar++) {
4321  delete [] Data[iVar];
4322  }
4323  delete [] Data;
4324 
4325  }
4326 }
4327 
4328 void COutputLegacy::SetConvHistory_Header(ofstream *ConvHist_file, CConfig *config, unsigned short val_iZone, unsigned short val_iInst) {
4329  char cstr[200], buffer[50], turb_resid[1000], adj_turb_resid[1000];
4330  unsigned short iMarker_Monitoring;
4331  string Monitoring_Tag, monitoring_coeff, aeroelastic_coeff, turbo_coeff;
4332 
4333  bool rotating_frame = config->GetRotating_Frame();
4334  bool aeroelastic = config->GetAeroelastic_Simulation();
4335  bool equiv_area = config->GetEquivArea();
4336  bool buffet = (config->GetBuffet_Monitoring() || config->GetKind_ObjFunc() == BUFFET_SENSOR);
4337  bool engine = ((config->GetnMarker_EngineInflow() != 0) || (config->GetnMarker_EngineExhaust() != 0));
4338  bool actuator_disk = ((config->GetnMarker_ActDiskInlet() != 0) || (config->GetnMarker_ActDiskOutlet() != 0));
4339  bool turbulent = ((config->GetKind_Solver() == RANS) || (config->GetKind_Solver() == ADJ_RANS) ||
4340  (config->GetKind_Solver() == DISC_ADJ_RANS) || (config->GetKind_Solver() == DISC_ADJ_INC_RANS) ||
4341  (config->GetKind_Solver() == INC_RANS));
4342  bool cont_adj = config->GetContinuous_Adjoint();
4343  bool disc_adj = config->GetDiscrete_Adjoint();
4344  bool frozen_visc = (cont_adj && config->GetFrozen_Visc_Cont()) ||( disc_adj && config->GetFrozen_Visc_Disc());
4345  bool inv_design = (config->GetInvDesign_Cp() || config->GetInvDesign_HeatFlux());
4346 
4347  bool output_surface = (config->GetnMarker_Analyze() != 0);
4348  bool output_comboObj = (config->GetnObj() > 1);
4349  bool output_per_surface = config->GetWrt_Surface();
4350  bool turbo = config->GetBoolTurbomachinery();
4351  unsigned short direct_diff = config->GetDirectDiff();
4352 
4353  bool compressible = (config->GetKind_Regime() == COMPRESSIBLE);
4354  bool incompressible = (config->GetKind_Regime() == INCOMPRESSIBLE);
4355  bool incload = config->GetIncrementalLoad();
4356 
4357  bool thermal = false; /* Flag for whether to print heat flux values */
4358  bool weakly_coupled_heat = config->GetWeakly_Coupled_Heat();
4359 
4360  if (config->GetKind_Solver() == RANS || config->GetKind_Solver() == NAVIER_STOKES ||
4361  config->GetKind_Solver() == INC_RANS || config->GetKind_Solver() == INC_NAVIER_STOKES) {
4362  thermal = true;
4363  }
4364 
4365  /*--- Write file name with extension ---*/
4366  string filename = config->GetConv_FileName();
4367  string hist_ext = ".csv";
4368  if (config->GetTabular_FileFormat() == TAB_TECPLOT) hist_ext = ".dat";
4369 
4370  if(config->GetnZone() > 1){
4371  filename = config->GetMultizone_HistoryFileName(filename, val_iZone, hist_ext);
4372  }
4373  if(config->GetnTimeInstances() > 1){
4374  filename = config->GetMultiInstance_HistoryFileName(filename, val_iInst);
4375  }
4376 
4377  if (config->GetTime_Domain() && config->GetRestart()) {
4378  filename = config->GetUnsteady_FileName(filename, config->GetRestart_Iter(), hist_ext);
4379  }
4380 
4381  strcpy (cstr, filename.data());
4382 
4383  ConvHist_file->open(cstr, ios::out);
4384  ConvHist_file->precision(15);
4385 
4386  /*--- Begin of the header ---*/
4387 
4388  char begin[]= "\"Iteration\"";
4389 
4390  /*--- Header for the coefficients ---*/
4391 
4392  char flow_coeff[]= ",\"CL\",\"CD\",\"CSF\",\"CMx\",\"CMy\",\"CMz\",\"CFx\",\"CFy\",\"CFz\",\"CL/CD\",\"AoA\",\"Custom_ObjFunc\"";
4393  char heat_coeff[]= ",\"HeatFlux_Total\",\"HeatFlux_Maximum\",\"Temperature_Total\"";
4394  char equivalent_area_coeff[]= ",\"CEquivArea\",\"CNearFieldOF\"";
4395  char buffet_coeff[]= ",\"Buffet_Metric\"";
4396  char engine_coeff[]= ",\"NetThrust\",\"Power\",\"AeroCDrag\",\"SolidCDrag\",\"Radial_Distortion\",\"Circumferential_Distortion\"";
4397  char rotating_frame_coeff[]= ",\"CMerit\",\"CT\",\"CQ\"";
4398  char fem_coeff[]= ",\"VM_Stress\",\"Force_Coeff\"";
4399  char fem_incload[]= ",\"IncLoad\"";
4400  char adj_coeff[]= ",\"Sens_Geo\",\"Sens_Mach\",\"Sens_AoA\",\"Sens_Press\",\"Sens_Temp\",\"Sens_AoS\"";
4401  char adj_inc_coeff[]=",\"Sens_Geo\",\"Sens_Vin\",\"Sens_Pout\",\"Sens_Temp\"";
4402  char adj_turbo_coeff[]=",\"Sens_Geo\",\"Sens_PressOut\",\"Sens_TotTempIn\"";
4403  char surface_outputs[]= ",\"Avg_MassFlow\",\"Avg_Mach\",\"Avg_Temp\",\"Avg_Press\",\"Avg_Density\",\"Avg_Enthalpy\",\"Avg_NormalVel\",\"Uniformity\",\"Secondary_Strength\",\"Momentum_Distortion\",\"Secondary_Over_Uniformity\",\"Avg_TotalTemp\",\"Avg_TotalPress\",\"Pressure_Drop\"";
4404  char Cp_inverse_design[]= ",\"Cp_Diff\"";
4405  char Heat_inverse_design[]= ",\"HeatFlux_Diff\"";
4406  char d_flow_coeff[] = ",\"D(CL)\",\"D(CD)\",\"D(CSF)\",\"D(CMx)\",\"D(CMy)\",\"D(CMz)\",\"D(CFx)\",\"D(CFy)\",\"D(CFz)\",\"D(CL/CD)\",\"D(Custom_ObjFunc)\"";
4407  char d_thermal_coeff[] = ",\"D(HeatFlux_Total)\",\"D(HeatFlux_Maximum)\"";
4408  char d_engine[] = ",\"D(NetThrust)\",\"D(Power)\",\"D(AeroCDrag)\",\"D(SolidCDrag)\",\"D(Radial_Distortion)\",\"D(Circumferential_Distortion)\"";
4409  char d_turbo_coeff[] = ",\"D(TotalPressureLoss_0)\",\"D(FlowAngleOut_0)\",\"D(TotalEfficency)\",\"D(TotalStaticEfficiency)\", \"D(EntropyGen)\"";
4410  char d_surface_outputs[]= ",\"D(Uniformity)\",\"D(Secondary_Strength)\",\"D(Momentum_Distortion)\",\"D(Secondary_Over_Uniformity)\",\"D(Pressure_Drop)\"";
4411 
4412  /*--- Find the markers being monitored and create a header for them ---*/
4413 
4414  for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++) {
4415  Monitoring_Tag = config->GetMarker_Monitoring_TagBound(iMarker_Monitoring);
4416  monitoring_coeff += ",\"CL_" + Monitoring_Tag + "\"";
4417  monitoring_coeff += ",\"CD_" + Monitoring_Tag + "\"";
4418  monitoring_coeff += ",\"CSF_" + Monitoring_Tag + "\"";
4419  monitoring_coeff += ",\"CL/CD_" + Monitoring_Tag + "\"";
4420  monitoring_coeff += ",\"CFx_" + Monitoring_Tag + "\"";
4421  monitoring_coeff += ",\"CFy_" + Monitoring_Tag + "\"";
4422  monitoring_coeff += ",\"CFz_" + Monitoring_Tag + "\"";
4423  monitoring_coeff += ",\"CMx_" + Monitoring_Tag + "\"";
4424  monitoring_coeff += ",\"CMy_" + Monitoring_Tag + "\"";
4425  monitoring_coeff += ",\"CMz_" + Monitoring_Tag + "\"";
4426  if(buffet) monitoring_coeff += ",\"Buffet_Metric_" + Monitoring_Tag + "\"";
4427  aeroelastic_coeff += ",\"plunge_" + Monitoring_Tag + "\"";
4428  aeroelastic_coeff += ",\"pitch_" + Monitoring_Tag + "\"";
4429  }
4430 
4431  if (turbo){
4432  for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_TurboPerformance(); iMarker_Monitoring++) {
4433 
4434  stringstream tag;
4435  tag << iMarker_Monitoring + 1;
4436 
4437  turbo_coeff += ",\"TotalPressureLoss_" + tag.str() + "\"";
4438  turbo_coeff += ",\"KineticEnergyLoss_" + tag.str() + "\"";
4439  turbo_coeff += ",\"EntropyGen_" + tag.str() + "\"";
4440  turbo_coeff += ",\"EulerianWork_" + tag.str() + "\"";
4441  turbo_coeff += ",\"PressureRatio_" + tag.str() + "\"";
4442  turbo_coeff += ",\"FlowAngleIn_" + tag.str() + "\"";
4443  turbo_coeff += ",\"FlowAngleOut_" + tag.str() + "\"";
4444  turbo_coeff += ",\"AbsFlowAngleIn_" + tag.str() + "\"";
4445  turbo_coeff += ",\"AbsFlowAngleOut_" + tag.str() + "\"";
4446  turbo_coeff += ",\"MassFlowIn_" + tag.str() + "\"";
4447  turbo_coeff += ",\"MassFlowOut_" + tag.str() + "\"";
4448  turbo_coeff += ",\"MachIn_" + tag.str() + "\"";
4449  turbo_coeff += ",\"MachOut_" + tag.str() + "\"";
4450  // different from zero only in multi-zone computation
4451  turbo_coeff += ",\"TotalEfficiency_" + tag.str() + "\"";
4452  turbo_coeff += ",\"TotalStaticEfficiency_" + tag.str() + "\"";
4453 
4454  }
4455  }
4456 
4457  char combo_obj[] = ",\"ComboObj\"";
4458 
4459  /*--- Header for the residuals ---*/
4460 
4461  char flow_resid[]= ",\"Res_Flow[0]\",\"Res_Flow[1]\",\"Res_Flow[2]\",\"Res_Flow[3]\",\"Res_Flow[4]\"";
4462  char adj_flow_resid[]= ",\"Res_AdjFlow[0]\",\"Res_AdjFlow[1]\",\"Res_AdjFlow[2]\",\"Res_AdjFlow[3]\",\"Res_AdjFlow[4]\"";
4463  switch (config->GetKind_Turb_Model()) {
4464  case SA:case SA_NEG:case SA_E: case SA_COMP: case SA_E_COMP:
4465  SPRINTF (turb_resid, ",\"Res_Turb[0]\"");
4466  break;
4467  case SST:case SST_SUST:
4468  SPRINTF (turb_resid, ",\"Res_Turb[0]\",\"Res_Turb[1]\"");
4469  break;
4470  }
4471  switch (config->GetKind_Turb_Model()) {
4472  case SA:case SA_NEG:case SA_E: case SA_COMP: case SA_E_COMP:
4473  SPRINTF (adj_turb_resid, ",\"Res_AdjTurb[0]\"");
4474  break;
4475  case SST:case SST_SUST:
4476  SPRINTF (adj_turb_resid, ",\"Res_AdjTurb[0]\",\"Res_AdjTurb[1]\"");
4477  break;
4478  }
4479  char fem_resid[]= ",\"Res_FEM[0]\",\"Res_FEM[1]\",\"Res_FEM[2]\"";
4480  char heat_resid[]= ",\"Res_Heat\"";
4481 
4482  /*--- End of the header ---*/
4483 
4484  char end[]= ",\"Linear_Solver_Iterations\",\"CFL_Number\",\"Time(min)\"\n";
4485  char endfea[]= ",\"Linear_Solver_Iterations\",\"Time(min)\"\n";
4486 
4487  if ((config->GetTabular_FileFormat() == TECPLOT) ||
4488  (config->GetTabular_FileFormat() == TECPLOT_BINARY)) {
4489  ConvHist_file[0] << "TITLE = \"SU2 Simulation\"" << endl;
4490  ConvHist_file[0] << "VARIABLES = ";
4491  }
4492 
4493  /*--- Write the header, case depending ---*/
4494 
4495  switch (config->GetKind_Solver()) {
4496 
4497  case EULER : case NAVIER_STOKES: case RANS :
4498  case INC_EULER : case INC_NAVIER_STOKES: case INC_RANS :
4499  case FEM_EULER : case FEM_NAVIER_STOKES: case FEM_RANS : case FEM_LES:
4500  ConvHist_file[0] << begin;
4501  if (!turbo) ConvHist_file[0] << flow_coeff;
4502  if (buffet) ConvHist_file[0] << buffet_coeff;
4503  if (turbo) ConvHist_file[0] << turbo_coeff;
4504  if (thermal && !turbo) ConvHist_file[0] << heat_coeff;
4505  if (equiv_area) ConvHist_file[0] << equivalent_area_coeff;
4506  if (engine || actuator_disk) ConvHist_file[0] << engine_coeff;
4507  if (inv_design) {
4508  ConvHist_file[0] << Cp_inverse_design;
4509  if (thermal && !turbo) ConvHist_file[0] << Heat_inverse_design;
4510  }
4511  if (rotating_frame && !turbo) ConvHist_file[0] << rotating_frame_coeff;
4512 
4513  ConvHist_file[0] << flow_resid;
4514  if (turbulent) ConvHist_file[0] << turb_resid;
4515  if (weakly_coupled_heat) ConvHist_file[0] << heat_resid;
4516  if (aeroelastic) ConvHist_file[0] << aeroelastic_coeff;
4517  if (output_per_surface) ConvHist_file[0] << monitoring_coeff;
4518  if (output_surface) ConvHist_file[0] << surface_outputs;
4519  if (direct_diff != NO_DERIVATIVE) {
4520  if (!turbo) ConvHist_file[0] << d_flow_coeff;
4521  else ConvHist_file[0] << d_turbo_coeff;
4522  if (engine || actuator_disk) ConvHist_file[0] << d_engine;
4523  if (thermal) ConvHist_file[0] << d_thermal_coeff;
4524  if (output_surface) ConvHist_file[0] << d_surface_outputs;
4525  }
4526  if (output_comboObj) ConvHist_file[0] << combo_obj;
4527  ConvHist_file[0] << end;
4528 
4529  break;
4530 
4531  case ADJ_EULER : case ADJ_NAVIER_STOKES : case ADJ_RANS:
4534  if (!turbo) {
4535  if (compressible) {
4536  ConvHist_file[0] << begin << adj_coeff << adj_flow_resid;
4537  }
4538  if (incompressible) {
4539  ConvHist_file[0] << begin << adj_inc_coeff << adj_flow_resid;
4540  }
4541  }
4542  else ConvHist_file[0] << begin << adj_turbo_coeff << adj_flow_resid;
4543  if ((turbulent) && (!frozen_visc)) ConvHist_file[0] << adj_turb_resid;
4544  ConvHist_file[0] << end;
4545  break;
4546 
4547  case HEAT_EQUATION_FVM:
4548  ConvHist_file[0] << begin << heat_coeff;
4549  ConvHist_file[0] << heat_resid << end;
4550  break;
4551 
4552  case FEM_ELASTICITY:
4553  ConvHist_file[0] << begin << fem_coeff;
4554  if (incload) ConvHist_file[0] << fem_incload;
4555  ConvHist_file[0] << fem_resid << endfea;
4556  break;
4557 
4558  case DISC_ADJ_FEM:
4559  ConvHist_file[0] << begin << fem_coeff;
4560  ConvHist_file[0] << fem_resid << endfea;
4561  break;
4562 
4563  }
4564 
4565  if (config->GetTabular_FileFormat() == TECPLOT ||
4566  config->GetTabular_FileFormat() == TECPLOT_BINARY) {
4567  ConvHist_file[0] << "ZONE T= \"Convergence history\"" << endl;
4568  }
4569 
4570 }
4571 
4572 
4573 void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file,
4574  CGeometry ****geometry,
4575  CSolver *****solver_container,
4576  CConfig **config,
4577  CIntegration ****integration,
4578  bool DualTime_Iteration,
4579  su2double timeused,
4580  unsigned short val_iZone,
4581  unsigned short val_iInst) {
4582 
4583  bool output_surface = (config[val_iZone]->GetnMarker_Analyze() != 0);
4584  bool output_comboObj = (config[val_iZone]->GetnObj() > 1);
4585  bool fluid_structure = (config[val_iZone]->GetFSI_Simulation());
4586  bool fea = ((config[val_iZone]->GetKind_Solver()== FEM_ELASTICITY)||(config[val_iZone]->GetKind_Solver()== DISC_ADJ_FEM));
4587  unsigned long iIntIter = config[val_iZone]->GetInnerIter();
4588  unsigned long iExtIter = config[val_iZone]->GetInnerIter();
4589  unsigned short FinestMesh = config[val_iZone]->GetFinestMesh();
4590  unsigned short nZone = config[val_iZone]->GetnZone();
4591  unsigned short nInst = config[val_iZone]->GetnTimeInstances();
4592  bool cont_adj = config[val_iZone]->GetContinuous_Adjoint();
4593  bool disc_adj = config[val_iZone]->GetDiscrete_Adjoint();
4594  bool energy = config[val_iZone]->GetEnergy_Equation();
4595  bool incload = config[val_iZone]->GetIncrementalLoad();
4596  bool fixed_cl = config[val_iZone]->GetFixed_CL_Mode();
4597  bool output_files = true;
4598 
4599  bool compressible = (config[val_iZone]->GetKind_Regime() == COMPRESSIBLE);
4600  bool incompressible = (config[val_iZone]->GetKind_Regime() == INCOMPRESSIBLE);
4601 
4602  if (!disc_adj && !cont_adj && !DualTime_Iteration) {
4603 
4604  if (fixed_cl &&
4605  (solver_container[val_iZone][val_iInst][MESH_0][FLOW_SOL]->GetStart_AoA_FD()) &&
4606  (iExtIter != solver_container[val_iZone][val_iInst][MESH_0][FLOW_SOL]->GetIter_Update_AoA())) {
4607  output_files = false;
4608  }
4609 
4610  if (fea || fluid_structure) output_files = false;
4611 
4612  /*--- We need to evaluate some of the objective functions to write the value on the history file ---*/
4613 
4614  if (((iExtIter % (config[val_iZone]->GetWrt_Sol_Freq())) == 0) ||
4615  (!fixed_cl && (iExtIter == (config[val_iZone]->GetnInner_Iter()-1))) ||
4616  /*--- If CL mode we need to compute the complete solution at two very particular iterations ---*/
4617  (fixed_cl && (iExtIter == (config[val_iZone]->GetnInner_Iter()-2) ||
4618  (solver_container[val_iZone][val_iInst][MESH_0][FLOW_SOL]->GetStart_AoA_FD() &&
4619  iExtIter == solver_container[val_iZone][val_iInst][MESH_0][FLOW_SOL]->GetIter_Update_AoA())))) {
4620 
4621 
4622  if ((rank == MASTER_NODE) && output_files) cout << endl << "------------------------ Evaluate Special Output ------------------------";
4623 
4624  switch (config[val_iZone]->GetKind_Solver()) {
4625 
4626  case EULER: case NAVIER_STOKES: case RANS:
4627  case INC_EULER: case INC_NAVIER_STOKES: case INC_RANS:
4628  /*--- For specific applications, evaluate and plot the surface. ---*/
4629 
4630  if (config[val_iZone]->GetnMarker_Analyze() != 0) {
4631  SpecialOutput_AnalyzeSurface(solver_container[val_iZone][val_iInst][MESH_0][FLOW_SOL],
4632  geometry[val_iZone][val_iInst][MESH_0], config[val_iZone], output_files);
4633  }
4634 
4635  /*--- For specific applications, evaluate and plot the surface. ---*/
4636 
4637  if ((config[val_iZone]->GetnMarker_Analyze() != 0) && compressible) {
4638  SpecialOutput_Distortion(solver_container[val_iZone][val_iInst][MESH_0][FLOW_SOL],
4639  geometry[val_iZone][val_iInst][MESH_0], config[val_iZone], output_files);
4640  }
4641 
4642  /*--- For specific applications, evaluate and plot the equivalent area. ---*/
4643 
4644  if (config[val_iZone]->GetnMarker_NearFieldBound() != 0) {
4645  SpecialOutput_SonicBoom(solver_container[val_iZone][val_iInst][MESH_0][FLOW_SOL],
4646  geometry[val_iZone][val_iInst][MESH_0], config[val_iZone], output_files);
4647  }
4648 
4649  /*--- For specific applications, evaluate and plot the cp coefficent at different stations. ---*/
4650 
4651  if (config[val_iZone]->GetPlot_Section_Forces()) {
4652  SpecialOutput_SpanLoad(solver_container[val_iZone][val_iInst][MESH_0][FLOW_SOL],
4653  geometry[val_iZone][val_iInst][MESH_0], config[val_iZone], output_files);
4654  }
4655 
4656  break;
4657  }
4658 
4659  /*--- Output a file with the forces breakdown. ---*/
4660 
4661  if (config[val_iZone]->GetTime_Marching() == HARMONIC_BALANCE) {
4662  SpecialOutput_HarmonicBalance(solver_container, geometry, config, val_iInst, nInst, output_files);
4663  }
4664 
4665  /*--- Compute span-wise values file for turbomachinery. ---*/
4666 
4667  if (config[val_iZone]->GetBoolTurbomachinery()) {
4668  SpecialOutput_Turbo(solver_container, geometry, config, val_iZone, output_files);
4669  }
4670 
4671  /*--- Output a file with the forces breakdown. ---*/
4672 
4673  SpecialOutput_ForcesBreakdown(solver_container, geometry, config, val_iZone, output_files);
4674 
4675  if ((rank == MASTER_NODE) && output_files) cout << "-------------------------------------------------------------------------" << endl << endl;
4676 
4677  }
4678 
4679  }
4680 
4681  /*--- Output using only the master node ---*/
4682 
4683  if (rank == MASTER_NODE) {
4684 
4685  /*-- Compute the total objective if a "combo" objective is used ---*/
4686 
4687  if (output_comboObj) {
4688  solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->SetTotal_ComboObj(0.0);
4689  switch (config[val_iZone]->GetKind_Solver()) {
4690  case EULER: case NAVIER_STOKES: case RANS:
4691  case INC_EULER: case INC_NAVIER_STOKES: case INC_RANS:
4692  solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->Evaluate_ObjFunc(config[val_iZone]);
4693  break;
4694  }
4695  }
4696 
4697  unsigned long ExtIter_OffSet = config[val_iZone]->GetExtIter_OffSet();
4698  if (config[val_iZone]->GetTime_Marching() == DT_STEPPING_1ST ||
4699  config[val_iZone]->GetTime_Marching() == DT_STEPPING_2ND)
4700  ExtIter_OffSet = 0;
4701 
4702  /*--- WARNING: These buffers have hard-coded lengths. Note that you
4703  may have to adjust them to be larger if adding more entries. ---*/
4704 
4705  char begin[1000], direct_coeff[1000], heat_coeff[1000], equivalent_area_coeff[1000], engine_coeff[1000], rotating_frame_coeff[1000], Cp_inverse_design[1000], Heat_inverse_design[1000], surface_coeff[1000], aeroelastic_coeff[1000], monitoring_coeff[10000], buffet_coeff[1000],
4706  adjoint_coeff[1000], flow_resid[1000], adj_flow_resid[1000], turb_resid[1000], trans_resid[1000],
4707  adj_turb_resid[1000],
4708  begin_fem[1000], fem_coeff[1000], heat_resid[1000], combo_obj[1000],
4709  fem_resid[1000], end[1000], end_fem[1000], surface_outputs[1000], d_surface_outputs[1000], d_direct_coeff[1000], turbo_coeff[10000];
4710 
4711 
4712  su2double dummy = 0.0, *Coord;
4713  unsigned short iVar, iMarker_Monitoring;
4714 
4715  unsigned long LinSolvIter = 0, iPointMaxResid;
4716  su2double timeiter = timeused/su2double(iExtIter+1);
4717 
4718  unsigned short nDim = geometry[val_iZone][val_iInst][FinestMesh]->GetnDim();
4719 
4720 
4721  bool rotating_frame = config[val_iZone]->GetRotating_Frame();
4722  bool aeroelastic = config[val_iZone]->GetAeroelastic_Simulation();
4723  bool equiv_area = config[val_iZone]->GetEquivArea();
4724  bool engine = ((config[val_iZone]->GetnMarker_EngineInflow() != 0) || (config[val_iZone]->GetnMarker_EngineExhaust() != 0));
4725  bool actuator_disk = ((config[val_iZone]->GetnMarker_ActDiskInlet() != 0) || (config[val_iZone]->GetnMarker_ActDiskOutlet() != 0));
4726  bool inv_design = (config[val_iZone]->GetInvDesign_Cp() || config[val_iZone]->GetInvDesign_HeatFlux());
4727  bool transition = (config[val_iZone]->GetKind_Trans_Model() == LM);
4728  bool thermal = (config[val_iZone]->GetKind_Solver() == RANS || config[val_iZone]->GetKind_Solver() == NAVIER_STOKES ||
4729  config[val_iZone]->GetKind_Solver() == INC_NAVIER_STOKES || config[val_iZone]->GetKind_Solver() == INC_RANS );
4730  bool turbulent = ((config[val_iZone]->GetKind_Solver() == RANS) || (config[val_iZone]->GetKind_Solver() == ADJ_RANS) ||
4731  (config[val_iZone]->GetKind_Solver() == DISC_ADJ_RANS) || config[val_iZone]->GetKind_Solver() == INC_RANS ||
4732  config[val_iZone]->GetKind_Solver() == DISC_ADJ_INC_RANS);
4733  bool adjoint = cont_adj || disc_adj;
4734  bool frozen_visc = (cont_adj && config[val_iZone]->GetFrozen_Visc_Cont()) ||( disc_adj && config[val_iZone]->GetFrozen_Visc_Disc());
4735  bool heat = ((config[val_iZone]->GetKind_Solver() == HEAT_EQUATION_FVM) || (config[val_iZone]->GetWeakly_Coupled_Heat()));
4736  bool weakly_coupled_heat = config[val_iZone]->GetWeakly_Coupled_Heat();
4737  bool flow = (config[val_iZone]->GetKind_Solver() == EULER) || (config[val_iZone]->GetKind_Solver() == NAVIER_STOKES) ||
4738  (config[val_iZone]->GetKind_Solver() == RANS) || (config[val_iZone]->GetKind_Solver() == FEM_EULER) ||
4739  (config[val_iZone]->GetKind_Solver() == FEM_NAVIER_STOKES) || (config[val_iZone]->GetKind_Solver() == FEM_RANS) ||
4740  (config[val_iZone]->GetKind_Solver() == FEM_LES) || (config[val_iZone]->GetKind_Solver() == ADJ_EULER) ||
4741  (config[val_iZone]->GetKind_Solver() == ADJ_NAVIER_STOKES) || (config[val_iZone]->GetKind_Solver() == ADJ_RANS) ||
4742  (config[val_iZone]->GetKind_Solver() == INC_EULER) || (config[val_iZone]->GetKind_Solver() == INC_NAVIER_STOKES) ||
4743  (config[val_iZone]->GetKind_Solver() == INC_RANS);
4744  bool buffet = (config[val_iZone]->GetBuffet_Monitoring() || config[val_iZone]->GetKind_ObjFunc() == BUFFET_SENSOR);
4745 
4746  bool fem = ((config[val_iZone]->GetKind_Solver() == FEM_ELASTICITY) || // FEM structural solver.
4747  (config[val_iZone]->GetKind_Solver() == DISC_ADJ_FEM));
4748  bool linear_analysis = (config[val_iZone]->GetGeometricConditions() == SMALL_DEFORMATIONS); // Linear analysis.
4749  bool nonlinear_analysis = (config[val_iZone]->GetGeometricConditions() == LARGE_DEFORMATIONS); // Nonlinear analysis.
4750  bool fsi = (config[val_iZone]->GetFSI_Simulation()); // FEM structural solver.
4751  bool discadj_fem = (config[val_iZone]->GetKind_Solver() == DISC_ADJ_FEM);
4752 
4753  bool turbo = config[val_iZone]->GetBoolTurbomachinery();
4754 
4755  unsigned short nTurboPerf = config[val_iZone]->GetnMarker_TurboPerformance();
4756 
4757  bool output_per_surface = config[val_iZone]->GetWrt_Surface();
4758 
4759  unsigned short direct_diff = config[val_iZone]->GetDirectDiff();
4760 
4761  long ExtraHeatOutputZone = config[val_iZone]->GetExtraHeatOutputZone() - 1;
4762  bool extra_heat_output = false;
4763  su2double Extra_Total_Heat = 0.0;
4764  //su2double Extra_Total_Temperature = 0.0;
4765  su2double Extra_Heat_Residual = 0.0;
4766 
4767  if (ExtraHeatOutputZone > -1) {
4768  if (ExtraHeatOutputZone > nZone) {
4769  SU2_MPI::Error("Error in output routine: Extra output zone number exceeds total number of zones.", CURRENT_FUNCTION);
4770  }
4771  else if ((config[ExtraHeatOutputZone]->GetKind_Solver() != HEAT_EQUATION_FVM)) {
4772  SU2_MPI::Error("Error in output routine: No heat solver in extra output zone.", CURRENT_FUNCTION);
4773  }
4774  else {
4775  extra_heat_output = true;
4776  }
4777  }
4778 
4779  /*--- Initialize variables to store information from all domains (direct solution) ---*/
4780 
4781  su2double Total_CL = 0.0, Total_CD = 0.0, Total_CSF = 0.0, Total_CMx = 0.0, Total_CMy = 0.0, Total_CMz = 0.0, Total_CEff = 0.0,
4782  Total_CEquivArea = 0.0, Total_CNearFieldOF = 0.0, Total_CFx = 0.0, Total_CFy = 0.0, Total_CFz = 0.0, Total_CMerit = 0.0,
4783  Total_CT = 0.0, Total_CQ = 0.0,
4784  Total_Heat = 0.0, Total_MaxHeat = 0.0, Total_Temperature = 0.0, Total_Custom_ObjFunc = 0.0,
4785  Total_ComboObj = 0.0, Total_NetThrust = 0.0, Total_Power = 0.0, Total_AeroCD = 0.0, Total_SolidCD = 0.0, Total_IDR = 0.0, Total_IDC = 0.0,
4786  Total_AoA = 0.0, Total_Buffet_Metric = 0.0;
4787  su2double Surface_MassFlow = 0.0, Surface_Mach = 0.0, Surface_Temperature = 0.0, Surface_Pressure = 0.0, Surface_Density = 0.0, Surface_Enthalpy = 0.0, Surface_NormalVelocity = 0.0, Surface_TotalTemperature = 0.0, Surface_TotalPressure = 0.0, Surface_Uniformity = 0.0, Surface_SecondaryStrength = 0.0,Surface_MomentumDistortion = 0.0, Surface_SecondOverUniform = 0.0, Surface_PressureDrop = 0.0;
4788 
4789  su2double Total_ForceCoeff = 0.0, Total_VMStress = 0.0, Total_IncLoad = 0.0;
4790  su2double Total_SensE = 0.0, Total_SensNu = 0.0;
4791 
4792  unsigned short iSpan;
4793 
4794  /*--- Initialize variables to store information from all domains (adjoint solution) ---*/
4795  su2double Total_Sens_Geo = 0.0, Total_Sens_Mach = 0.0, Total_Sens_AoA = 0.0;
4796  su2double Total_Sens_Press = 0.0, Total_Sens_Temp = 0.0;
4797 
4798  su2double Total_Sens_BPressure = 0.0;
4799  su2double Total_Sens_ModVel = 0.0;
4800 
4801  /*--- Initialize variables to store information from all domains (direct differentiation) ---*/
4802  su2double D_Total_CL = 0.0, D_Total_CD = 0.0, D_Total_CSF = 0.0, D_Total_CMx = 0.0, D_Total_CMy = 0.0, D_Total_CMz = 0.0, D_Total_CEff = 0.0, D_Total_CFx = 0.0,
4803  D_Total_CFy = 0.0, D_Total_CFz = 0.0, D_Total_NetThrust = 0.0, D_Total_Power = 0.0, D_Total_AeroCD = 0.0, D_Total_SolidCD = 0.0, D_Total_IDR = 0.0, D_Total_IDC = 0.0, D_Total_Custom_ObjFunc = 0.0, D_Total_Heat = 0.0, D_Total_MaxHeat = 0.0,
4804  D_TotalPressure_Loss = 0.0, D_FlowAngle_Out = 0.0, D_TotalStaticEfficiency = 0.0,
4805  D_TotalTotalEfficiency = 0.0, D_EntropyGen = 0.0,
4806  D_Surface_Uniformity = 0.0, D_Surface_SecondaryStrength = 0.0, D_Surface_MomentumDistortion = 0.0, D_Surface_SecondOverUniform = 0.0, D_Surface_PressureDrop = 0.0;
4807 
4808  /*--- Residual arrays ---*/
4809  su2double *residual_flow = NULL,
4810  *residual_turbulent = NULL,
4811  *residual_transition = NULL;
4812  su2double *residual_adjflow = NULL,
4813  *residual_adjturbulent = NULL,
4814  *residual_adjheat = NULL;
4815  su2double *residual_fea = NULL;
4816  su2double *residual_fem = NULL;
4817  su2double *residual_heat = NULL;
4818 
4819  /*--- Coefficients Monitored arrays ---*/
4820  su2double *aeroelastic_plunge = NULL,
4821  *aeroelastic_pitch = NULL,
4822  *Surface_CL = NULL,
4823  *Surface_CD = NULL,
4824  *Surface_CSF = NULL,
4825  *Surface_CEff = NULL,
4826  *Surface_CFx = NULL,
4827  *Surface_CFy = NULL,
4828  *Surface_CFz = NULL,
4829  *Surface_CMx = NULL,
4830  *Surface_CMy = NULL,
4831  *Surface_CMz = NULL,
4832  *Surface_Buffet_Metric = NULL;
4833 
4834  /*--- Initialize number of variables ---*/
4835  unsigned short nVar_Flow = 0, nVar_Turb = 0,
4836  nVar_Trans = 0, nVar_Heat = 0,
4837  nVar_AdjFlow = 0, nVar_AdjTurb = 0, nVar_AdjHeat = 0,
4838  nVar_FEM = 0;
4839 
4840  /*--- Direct problem variables ---*/
4841  if (compressible) nVar_Flow = nDim+2; else nVar_Flow = nDim+2;
4842  if (turbulent) {
4843  switch (config[val_iZone]->GetKind_Turb_Model()) {
4844  case SA: case SA_NEG: case SA_E: case SA_E_COMP: case SA_COMP: nVar_Turb = 1; break;
4845  case SST: case SST_SUST: nVar_Turb = 2; break;
4846  }
4847  }
4848  if (transition) nVar_Trans = 2;
4849  if (heat) nVar_Heat = 1;
4850 
4851  if (fem) {
4852  if (linear_analysis) nVar_FEM = nDim;
4853  if (nonlinear_analysis) nVar_FEM = 3;
4854 
4855  if (config[val_iZone]->GetKind_Solver() == DISC_ADJ_FEM) nVar_FEM = nDim;
4856 
4857  }
4858 
4859  /*--- Adjoint problem variables ---*/
4860  if (compressible) nVar_AdjFlow = nDim+2; else nVar_AdjFlow = nDim+2;
4861  if (turbulent) {
4862  switch (config[val_iZone]->GetKind_Turb_Model()) {
4863  case SA: case SA_NEG: case SA_E: case SA_E_COMP: case SA_COMP: nVar_AdjTurb = 1; break;
4864  case SST: case SST_SUST: nVar_AdjTurb = 2; break;
4865  }
4866  }
4867  if (weakly_coupled_heat) nVar_AdjHeat = 1;
4868 
4869  /*--- Allocate memory for the residual ---*/
4870  residual_flow = new su2double[nVar_Flow];
4871  residual_turbulent = new su2double[nVar_Turb];
4872  residual_transition = new su2double[nVar_Trans];
4873  residual_heat = new su2double[nVar_Heat];
4874  residual_fem = new su2double[nVar_FEM];
4875 
4876  residual_adjflow = new su2double[nVar_AdjFlow];
4877  residual_adjturbulent = new su2double[nVar_AdjTurb];
4878  residual_adjheat = new su2double[nVar_AdjHeat];
4879 
4880  /*--- Allocate memory for the coefficients being monitored ---*/
4881  aeroelastic_plunge = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
4882  aeroelastic_pitch = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
4883  Surface_CL = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
4884  Surface_CD = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
4885  Surface_CSF = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
4886  Surface_CEff = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
4887  Surface_CFx = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
4888  Surface_CFy = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
4889  Surface_CFz = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
4890  Surface_CMx = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
4891  Surface_CMy = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
4892  Surface_CMz = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
4893  if(buffet) Surface_Buffet_Metric = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
4894 
4895  /*--- Write information from nodes ---*/
4896 
4897  switch (config[val_iZone]->GetKind_Solver()) {
4898 
4899  case EULER: case NAVIER_STOKES: case RANS:
4900  case INC_EULER: case INC_NAVIER_STOKES: case INC_RANS:
4901  case FEM_EULER: case FEM_NAVIER_STOKES: case FEM_RANS: case FEM_LES:
4902  case ADJ_EULER: case ADJ_NAVIER_STOKES: case ADJ_RANS:
4905 
4906  /*--- Flow solution coefficients ---*/
4907 
4908  Total_CL = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CL();
4909  Total_CD = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CD();
4910  Total_CSF = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CSF();
4911  Total_CEff = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CEff();
4912  Total_CMx = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CMx();
4913  Total_CMy = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CMy();
4914  Total_CMz = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CMz();
4915  Total_CFx = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CFx();
4916  Total_CFy = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CFy();
4917  Total_CFz = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CFz();
4918  Total_ComboObj = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_ComboObj();
4919  Total_AoA = config[val_iZone]->GetAoA() - config[val_iZone]->GetAoA_Offset();
4920  Total_Custom_ObjFunc = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_Custom_ObjFunc();
4921 
4922  if (thermal) {
4923  Total_Heat = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_HeatFlux();
4924  Total_MaxHeat = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_MaxHeatFlux();
4925  Total_Temperature = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_AvgTemperature();
4926 
4927  if(weakly_coupled_heat) {
4928  Total_Heat = solver_container[val_iZone][val_iInst][FinestMesh][HEAT_SOL]->GetTotal_HeatFlux();
4929  Total_MaxHeat = solver_container[val_iZone][val_iInst][FinestMesh][HEAT_SOL]->GetTotal_MaxHeatFlux();
4930  Total_Temperature = solver_container[val_iZone][val_iInst][FinestMesh][HEAT_SOL]->GetTotal_AvgTemperature();
4931  }
4932  }
4933 
4934  if(buffet){
4935  Total_Buffet_Metric = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_Buffet_Metric();
4936  }
4937 
4938  if (direct_diff != NO_DERIVATIVE) {
4939  D_Total_CL = SU2_TYPE::GetDerivative(Total_CL);
4940  D_Total_CD = SU2_TYPE::GetDerivative(Total_CD);
4941  D_Total_CSF = SU2_TYPE::GetDerivative(Total_CSF);
4942  D_Total_CEff = SU2_TYPE::GetDerivative(Total_CEff);
4943  D_Total_CMx = SU2_TYPE::GetDerivative(Total_CMx);
4944  D_Total_CMy = SU2_TYPE::GetDerivative(Total_CMy);
4945  D_Total_CMz = SU2_TYPE::GetDerivative(Total_CMz);
4946  D_Total_CFx = SU2_TYPE::GetDerivative(Total_CFx);
4947  D_Total_CFy = SU2_TYPE::GetDerivative(Total_CFy);
4948  D_Total_CFz = SU2_TYPE::GetDerivative(Total_CFz);
4949  D_Total_Custom_ObjFunc = SU2_TYPE::GetDerivative(Total_Custom_ObjFunc);
4950 
4951  if (thermal) {
4952  D_Total_Heat = SU2_TYPE::GetDerivative(Total_Heat);
4953  D_Total_MaxHeat = SU2_TYPE::GetDerivative(Total_MaxHeat);
4954  //Davg Temp
4955  }
4956 
4957  if (engine || actuator_disk) {
4958  D_Total_NetThrust = SU2_TYPE::GetDerivative(Total_NetThrust);
4959  D_Total_Power = SU2_TYPE::GetDerivative(Total_Power);
4960  D_Total_AeroCD = SU2_TYPE::GetDerivative(Total_AeroCD);
4961  D_Total_SolidCD = SU2_TYPE::GetDerivative(Total_SolidCD);
4962  D_Total_IDR = SU2_TYPE::GetDerivative(Total_IDR);
4963  D_Total_IDC = SU2_TYPE::GetDerivative(Total_IDC);
4964  }
4965 
4966  }
4967 
4968  if (equiv_area) {
4969  Total_CEquivArea = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CEquivArea();
4970  Total_CNearFieldOF = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CNearFieldOF();
4971 
4972  Total_CEquivArea = config[val_iZone]->GetWeightCd()*Total_CD + (1.0-config[val_iZone]->GetWeightCd())*Total_CEquivArea;
4973  Total_CNearFieldOF = config[val_iZone]->GetWeightCd()*Total_CD + (1.0-config[val_iZone]->GetWeightCd())*Total_CNearFieldOF;
4974  }
4975 
4976  if (engine || actuator_disk) {
4977  Total_NetThrust = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_NetThrust();
4978  Total_Power = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_Power();
4979  Total_AeroCD = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_AeroCD();
4980  Total_SolidCD = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_SolidCD();
4981  Total_IDR = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_IDR();
4982  Total_IDC = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_IDC();
4983  }
4984 
4985  if (rotating_frame) {
4986  Total_CT = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CT();
4987  Total_CQ = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CQ();
4988  Total_CMerit = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CMerit();
4989  }
4990 
4991  if (aeroelastic) {
4992  /*--- Look over the markers being monitored and get the desired values ---*/
4993  for (iMarker_Monitoring = 0; iMarker_Monitoring < config[ZONE_0]->GetnMarker_Monitoring(); iMarker_Monitoring++) {
4994  aeroelastic_plunge[iMarker_Monitoring] = config[val_iZone]->GetAeroelastic_plunge(iMarker_Monitoring);
4995  aeroelastic_pitch[iMarker_Monitoring] = config[val_iZone]->GetAeroelastic_pitch(iMarker_Monitoring);
4996  }
4997  }
4998 
4999  if (output_per_surface) {
5000  /*--- Look over the markers being monitored and get the desired values ---*/
5001  for (iMarker_Monitoring = 0; iMarker_Monitoring < config[ZONE_0]->GetnMarker_Monitoring(); iMarker_Monitoring++) {
5002  Surface_CL[iMarker_Monitoring] = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetSurface_CL(iMarker_Monitoring);
5003  Surface_CD[iMarker_Monitoring] = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetSurface_CD(iMarker_Monitoring);
5004  Surface_CSF[iMarker_Monitoring] = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetSurface_CSF(iMarker_Monitoring);
5005  Surface_CEff[iMarker_Monitoring] = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetSurface_CEff(iMarker_Monitoring);
5006  Surface_CFx[iMarker_Monitoring] = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetSurface_CFx(iMarker_Monitoring);
5007  Surface_CFy[iMarker_Monitoring] = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetSurface_CFy(iMarker_Monitoring);
5008  Surface_CFz[iMarker_Monitoring] = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetSurface_CFz(iMarker_Monitoring);
5009  Surface_CMx[iMarker_Monitoring] = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetSurface_CMx(iMarker_Monitoring);
5010  Surface_CMy[iMarker_Monitoring] = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetSurface_CMy(iMarker_Monitoring);
5011  Surface_CMz[iMarker_Monitoring] = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetSurface_CMz(iMarker_Monitoring);
5012 
5013  if(buffet) Surface_Buffet_Metric[iMarker_Monitoring] = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetSurface_Buffet_Metric(iMarker_Monitoring);
5014  }
5015  }
5016 
5017  if (turbo) {
5018  /*--- Loop over the nMarker of turboperformance and get the desired values ---*/
5019  for (iMarker_Monitoring = 0; iMarker_Monitoring < nTurboPerf; iMarker_Monitoring++) {
5020  for(iSpan=0; iSpan<nSpanWiseSections+1; iSpan++){
5021  if ((iMarker_Monitoring == 0) && (direct_diff != NO_DERIVATIVE)){
5022  D_TotalPressure_Loss = SU2_TYPE::GetDerivative(TotalPressureLoss[iMarker_Monitoring][iSpan]);
5023  D_FlowAngle_Out = 180.0/PI_NUMBER*SU2_TYPE::GetDerivative(FlowAngleOut[iMarker_Monitoring][iSpan]);
5024  }
5025  }
5026  }
5027  if (direct_diff != NO_DERIVATIVE){
5028  D_TotalStaticEfficiency = SU2_TYPE::GetDerivative(TotalStaticEfficiency[nTurboPerf-1][nSpanWiseSections]);
5029  D_TotalTotalEfficiency = SU2_TYPE::GetDerivative(TotalTotalEfficiency[nTurboPerf-1][nSpanWiseSections]);
5030  D_EntropyGen = SU2_TYPE::GetDerivative(EntropyGen[nTurboPerf-1][nSpanWiseSections]);
5031  }
5032  }
5033 
5034  /*--- Get flux-averaged values at the specified surface ---*/
5035 
5036  if (output_surface) {
5037 
5038  unsigned short iMarker_Analyze = 0;
5039  Surface_MassFlow = config[ZONE_0]->GetSurface_MassFlow(iMarker_Analyze);
5040  Surface_Mach = config[ZONE_0]->GetSurface_Mach(iMarker_Analyze);
5041  Surface_Temperature = config[ZONE_0]->GetSurface_Temperature(iMarker_Analyze);
5042  Surface_Pressure = config[ZONE_0]->GetSurface_Pressure(iMarker_Analyze);
5043  Surface_Density = config[ZONE_0]->GetSurface_Density(iMarker_Analyze);
5044  Surface_Enthalpy = config[ZONE_0]->GetSurface_Enthalpy(iMarker_Analyze);
5045  Surface_NormalVelocity = config[ZONE_0]->GetSurface_NormalVelocity(iMarker_Analyze);
5046  Surface_Uniformity = config[ZONE_0]->GetSurface_Uniformity(iMarker_Analyze);
5047  Surface_SecondaryStrength = config[ZONE_0]->GetSurface_SecondaryStrength(iMarker_Analyze);
5048  Surface_MomentumDistortion = config[ZONE_0]->GetSurface_MomentumDistortion(iMarker_Analyze);
5049  Surface_SecondOverUniform = config[ZONE_0]->GetSurface_SecondOverUniform(iMarker_Analyze);
5050  Surface_TotalTemperature = config[ZONE_0]->GetSurface_TotalTemperature(iMarker_Analyze);
5051  Surface_TotalPressure = config[ZONE_0]->GetSurface_TotalPressure(iMarker_Analyze);
5052  Surface_PressureDrop = config[ZONE_0]->GetSurface_PressureDrop(iMarker_Analyze);
5053 
5054  if (direct_diff != NO_DERIVATIVE){
5055  D_Surface_Uniformity = SU2_TYPE::GetDerivative(Surface_Uniformity);
5056  D_Surface_SecondaryStrength = SU2_TYPE::GetDerivative(Surface_SecondaryStrength);
5057  D_Surface_MomentumDistortion = SU2_TYPE::GetDerivative(Surface_MomentumDistortion);
5058  D_Surface_SecondOverUniform = SU2_TYPE::GetDerivative(Surface_SecondOverUniform);
5059  D_Surface_PressureDrop = SU2_TYPE::GetDerivative(Surface_PressureDrop);
5060  }
5061  }
5062 
5063  /*--- Flow Residuals ---*/
5064 
5065  for (iVar = 0; iVar < nVar_Flow; iVar++)
5066  residual_flow[iVar] = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetRes_RMS(iVar);
5067 
5068  /*--- Turbulent residual ---*/
5069 
5070  if (turbulent) {
5071  for (iVar = 0; iVar < nVar_Turb; iVar++)
5072  residual_turbulent[iVar] = solver_container[val_iZone][val_iInst][FinestMesh][TURB_SOL]->GetRes_RMS(iVar);
5073  }
5074 
5075  if (weakly_coupled_heat) {
5076  for (iVar = 0; iVar < nVar_Heat; iVar++) {
5077  residual_heat[iVar] = solver_container[val_iZone][val_iInst][FinestMesh][HEAT_SOL]->GetRes_RMS(iVar);
5078  }
5079 
5080  }
5081 
5082  /*--- Transition residual ---*/
5083 
5084  if (transition) {
5085  for (iVar = 0; iVar < nVar_Trans; iVar++)
5086  residual_transition[iVar] = solver_container[val_iZone][val_iInst][FinestMesh][TRANS_SOL]->GetRes_RMS(iVar);
5087  }
5088 
5089 
5090  /*--- FEA residual ---*/
5091  // if (fluid_structure) {
5092  // for (iVar = 0; iVar < nVar_FEA; iVar++)
5093  // residual_fea[iVar] = solver_container[ZONE_0][FinestMesh][FEA_SOL]->GetRes_RMS(iVar);
5094  // }
5095 
5096  /*--- Iterations of the linear solver ---*/
5097 
5098  LinSolvIter = (unsigned long) solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetIterLinSolver();
5099 
5100  /*--- Adjoint solver ---*/
5101 
5102  if (adjoint) {
5103 
5104  /*--- Adjoint solution coefficients ---*/
5105 
5106  Total_Sens_Geo = solver_container[val_iZone][val_iInst][FinestMesh][ADJFLOW_SOL]->GetTotal_Sens_Geo();
5107  Total_Sens_Mach = solver_container[val_iZone][val_iInst][FinestMesh][ADJFLOW_SOL]->GetTotal_Sens_Mach();
5108  Total_Sens_AoA = solver_container[val_iZone][val_iInst][FinestMesh][ADJFLOW_SOL]->GetTotal_Sens_AoA() * PI_NUMBER / 180.0;
5109  Total_Sens_Press = solver_container[val_iZone][val_iInst][FinestMesh][ADJFLOW_SOL]->GetTotal_Sens_Press();
5110  Total_Sens_Temp = solver_container[val_iZone][val_iInst][FinestMesh][ADJFLOW_SOL]->GetTotal_Sens_Temp();
5111  Total_Sens_BPressure = solver_container[val_iZone][val_iInst][FinestMesh][ADJFLOW_SOL]->GetTotal_Sens_BPress();
5112  Total_Sens_ModVel = solver_container[val_iZone][val_iInst][FinestMesh][ADJFLOW_SOL]->GetTotal_Sens_ModVel();
5113 
5114  /*--- Adjoint flow residuals ---*/
5115 
5116  for (iVar = 0; iVar < nVar_AdjFlow; iVar++) {
5117  residual_adjflow[iVar] = solver_container[val_iZone][val_iInst][FinestMesh][ADJFLOW_SOL]->GetRes_RMS(iVar);
5118  }
5119 
5120  /*--- Adjoint turbulent residuals ---*/
5121 
5122  if (turbulent) {
5123  if (!frozen_visc) {
5124  for (iVar = 0; iVar < nVar_AdjTurb; iVar++)
5125  residual_adjturbulent[iVar] = solver_container[val_iZone][val_iInst][FinestMesh][ADJTURB_SOL]->GetRes_RMS(iVar);
5126  }
5127  }
5128 
5129  if (weakly_coupled_heat) {
5130  for (iVar = 0; iVar < nVar_Heat; iVar++) {
5131  residual_adjheat[iVar] = solver_container[val_iZone][val_iInst][FinestMesh][ADJHEAT_SOL]->GetRes_RMS(iVar);
5132  }
5133  }
5134 
5135  }
5136 
5137  break;
5138 
5139 
5140  case HEAT_EQUATION_FVM:
5141 
5142  /*--- Heat coefficients ---*/
5143 
5144  Total_Heat = solver_container[val_iZone][val_iInst][FinestMesh][HEAT_SOL]->GetTotal_HeatFlux();
5145  Total_MaxHeat = solver_container[val_iZone][val_iInst][FinestMesh][HEAT_SOL]->GetTotal_MaxHeatFlux();
5146  Total_Temperature = solver_container[val_iZone][val_iInst][FinestMesh][HEAT_SOL]->GetTotal_AvgTemperature();
5147 
5148  /*--- Heat Residuals ---*/
5149 
5150  for (iVar = 0; iVar < nVar_Heat; iVar++) {
5151  residual_heat[iVar] = solver_container[val_iZone][val_iInst][FinestMesh][HEAT_SOL]->GetRes_RMS(iVar);
5152  }
5153 
5154  break;
5155 
5156  case FEM_ELASTICITY:
5157 
5158  /*--- FEM coefficients -- As of now, this is the Von Mises Stress ---*/
5159 
5160  Total_VMStress = solver_container[val_iZone][val_iInst][FinestMesh][FEA_SOL]->GetTotal_CFEA();
5161 
5162  Total_ForceCoeff = solver_container[val_iZone][val_iInst][FinestMesh][FEA_SOL]->GetForceCoeff();
5163 
5164  Total_IncLoad = solver_container[val_iZone][val_iInst][FinestMesh][FEA_SOL]->GetLoad_Increment();
5165 
5166  LinSolvIter = (unsigned long) solver_container[val_iZone][val_iInst][FinestMesh][FEA_SOL]->GetIterLinSolver();
5167 
5168  /*--- Residuals: ---*/
5169  /*--- Linear analysis: RMS of the displacements in the nDim coordinates ---*/
5170  /*--- Nonlinear analysis: UTOL, RTOL and DTOL (defined in the Postprocessing function) ---*/
5171 
5172  if (linear_analysis) {
5173  for (iVar = 0; iVar < nVar_FEM; iVar++) {
5174  residual_fem[iVar] = solver_container[val_iZone][val_iInst][FinestMesh][FEA_SOL]->GetRes_RMS(iVar);
5175  }
5176  }
5177  else if (nonlinear_analysis) {
5178  for (iVar = 0; iVar < nVar_FEM; iVar++) {
5179  residual_fem[iVar] = solver_container[val_iZone][val_iInst][FinestMesh][FEA_SOL]->GetRes_FEM(iVar);
5180  }
5181  }
5182 
5183  break;
5184 
5185  case DISC_ADJ_FEM:
5186 
5187  /*--- FEM coefficients -- As of now, this is the Von Mises Stress ---*/
5188 
5189  Total_VMStress = solver_container[val_iZone][val_iInst][FinestMesh][FEA_SOL]->GetTotal_CFEA();
5190 
5191  /*--- Residuals: ---*/
5192  /*--- Linear analysis: RMS of the displacements in the nDim coordinates ---*/
5193  /*--- Nonlinear analysis: UTOL, RTOL and DTOL (defined in the Postprocessing function) ---*/
5194  for (iVar = 0; iVar < nVar_FEM; iVar++) {
5195  residual_fem[iVar] = solver_container[val_iZone][val_iInst][FinestMesh][ADJFEA_SOL]->GetRes_RMS(iVar);
5196  }
5197 
5198  break;
5199 
5200 
5201  }
5202 
5203  if (extra_heat_output) {
5204  Extra_Total_Heat = solver_container[ExtraHeatOutputZone][val_iInst][FinestMesh][HEAT_SOL]->GetTotal_HeatFlux();
5205  //Extra_Total_Temperature = solver_container[ExtraHeatOutputZone][val_iInst][FinestMesh][HEAT_SOL]->GetTotal_Temperature();
5206  Extra_Heat_Residual = log10(solver_container[ExtraHeatOutputZone][val_iInst][FinestMesh][HEAT_SOL]->GetRes_RMS(0));
5207  }
5208 
5209  /*--- Header frequency ---*/
5210 
5211  bool Unsteady = ((config[val_iZone]->GetTime_Marching() == DT_STEPPING_1ST) ||
5212  (config[val_iZone]->GetTime_Marching() == DT_STEPPING_2ND));
5213  bool In_NoDualTime = (!DualTime_Iteration && (iExtIter % config[val_iZone]->GetWrt_Con_Freq() == 0));
5214  bool In_DualTime_0 = (DualTime_Iteration && (iIntIter % config[val_iZone]->GetWrt_Con_Freq_DualTime() == 0));
5215  bool In_DualTime_1 = (!DualTime_Iteration && Unsteady);
5216  bool In_DualTime_2 = (Unsteady && DualTime_Iteration && (iExtIter % config[val_iZone]->GetWrt_Con_Freq() == 0));
5217  bool In_DualTime_3 = (Unsteady && !DualTime_Iteration && (iExtIter % config[val_iZone]->GetWrt_Con_Freq() == 0));
5218 
5219  /*--- Header frequency: analogy for dynamic structural analysis ---*/
5220  /*--- DualTime_Iteration is a bool we receive, which is true if it comes from FEM_StructuralIteration and false from SU2_CFD ---*/
5221  /*--- We maintain the name, as it is an input of the function ---*/
5222  /*--- The function GetWrt_Con_Freq_DualTime should be modified to be able to define different frequencies ---*/
5223  /*--- dynamic determines if the problem is, or not, time dependent ---*/
5224  bool dynamic = (config[val_iZone]->GetTime_Domain()); // Dynamic simulations.
5225  bool In_NoDynamic = (!DualTime_Iteration && (iExtIter % config[val_iZone]->GetWrt_Con_Freq() == 0));
5226  bool In_Dynamic_0 = (DualTime_Iteration && (iIntIter % config[val_iZone]->GetWrt_Con_Freq_DualTime() == 0));
5227  bool In_Dynamic_1 = (!DualTime_Iteration && nonlinear_analysis);
5228  bool In_Dynamic_2 = (nonlinear_analysis && DualTime_Iteration && (iExtIter % config[val_iZone]->GetWrt_Con_Freq() == 0));
5229  bool In_Dynamic_3 = (nonlinear_analysis && !DualTime_Iteration && (iExtIter % config[val_iZone]->GetWrt_Con_Freq() == 0));
5230 
5231  bool write_heads;
5232  if (Unsteady) write_heads = (iIntIter == 0);
5233  else write_heads = (((iExtIter % (config[val_iZone]->GetWrt_Con_Freq()*40)) == 0));
5234 
5235  bool write_turbo = (((iExtIter % (config[val_iZone]->GetWrt_Con_Freq()*40)) == 0) || (iExtIter == (config[val_iZone]->GetnInner_Iter() -1)));
5236 
5237  /*--- Analogous for dynamic problems (as of now I separate the problems, it may be worthy to do all together later on ---*/
5238  bool write_heads_FEM;
5239  if (nonlinear_analysis) write_heads_FEM = (iIntIter == 0);
5240  else write_heads_FEM = (((iExtIter % (config[val_iZone]->GetWrt_Con_Freq()*40)) == 0));
5241 
5242  if ( (!fem && ((In_NoDualTime || In_DualTime_0 || In_DualTime_1) && (In_NoDualTime || In_DualTime_2 || In_DualTime_3))) ||
5243  (fem && ( (In_NoDynamic || In_Dynamic_0 || In_Dynamic_1) && (In_NoDynamic || In_Dynamic_2 || In_Dynamic_3)))
5244  ) {
5245 
5246 
5247  /*--- Prepare the history file output, note that the dual
5248  time output don't write to the history file ---*/
5249  if (!DualTime_Iteration) {
5250 
5251  /*--- Write the begining of the history file ---*/
5252  SPRINTF(begin, "%12d", SU2_TYPE::Int(iExtIter+ExtIter_OffSet));
5253 
5254  /*--- Write the end of the history file ---*/
5255  SPRINTF (end, ", %12.10f, %12.10f, %12.10f\n", su2double(LinSolvIter), config[val_iZone]->GetCFL(MESH_0), timeused/60.0);
5256 
5257  /*--- Write the solution and residual of the history file ---*/
5258  switch (config[val_iZone]->GetKind_Solver()) {
5259 
5260  case EULER : case NAVIER_STOKES: case RANS:
5261  case INC_EULER : case INC_NAVIER_STOKES: case INC_RANS:
5262  case FEM_EULER : case FEM_NAVIER_STOKES: case FEM_RANS: case FEM_LES:
5263  case ADJ_EULER: case ADJ_NAVIER_STOKES: case ADJ_RANS: case DISC_ADJ_EULER:
5266 
5267  /*--- Direct coefficients ---*/
5268  SPRINTF (direct_coeff, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e",
5269  Total_CL, Total_CD, Total_CSF, Total_CMx, Total_CMy, Total_CMz, Total_CFx, Total_CFy,
5270  Total_CFz, Total_CEff, Total_AoA, Total_Custom_ObjFunc);
5271  if (buffet) SPRINTF (buffet_coeff, ", %14.8e", Total_Buffet_Metric);
5272  if (thermal || heat) SPRINTF (heat_coeff, ", %14.8e, %14.8e, %14.8e", Total_Heat, Total_MaxHeat, Total_Temperature);
5273  if (equiv_area) SPRINTF (equivalent_area_coeff, ", %14.8e, %14.8e", Total_CEquivArea, Total_CNearFieldOF);
5274  if (engine || actuator_disk) SPRINTF (engine_coeff, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", Total_NetThrust, Total_Power, Total_AeroCD, Total_SolidCD, Total_IDR, Total_IDC);
5275  if (rotating_frame) SPRINTF (rotating_frame_coeff, ", %14.8e, %14.8e, %14.8e", Total_CMerit, Total_CT, Total_CQ);
5276  if (inv_design) {
5277  SPRINTF (Cp_inverse_design, ", %14.8e", solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CpDiff());
5278  if (thermal && !turbo) SPRINTF (Heat_inverse_design, ", %14.8e", solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_HeatFluxDiff());
5279  }
5280 
5281  if (direct_diff != NO_DERIVATIVE) {
5282  if (!turbo)
5283  SPRINTF (d_direct_coeff, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e",
5284  D_Total_CL, D_Total_CD, D_Total_CSF, D_Total_CMx, D_Total_CMy, D_Total_CMz, D_Total_CFx, D_Total_CFy,
5285  D_Total_CFz, D_Total_CEff, D_Total_Custom_ObjFunc);
5286  else
5287  SPRINTF (d_direct_coeff, ", %12.10f, %12.10f, %12.10f, %12.10f, %12.10f", D_TotalPressure_Loss, D_FlowAngle_Out,
5288  D_TotalTotalEfficiency, D_TotalStaticEfficiency, D_EntropyGen);
5289  if (engine || actuator_disk)
5290  SPRINTF (d_direct_coeff, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e",
5291  D_Total_CL, D_Total_CD, D_Total_CSF, D_Total_CMx, D_Total_CMy, D_Total_CMz, D_Total_CFx, D_Total_CFy,
5292  D_Total_CFz, D_Total_CEff, D_Total_Custom_ObjFunc, D_Total_NetThrust, D_Total_Power, D_Total_AeroCD, D_Total_SolidCD, D_Total_IDR, D_Total_IDC);
5293  if (thermal)
5294  SPRINTF (d_direct_coeff, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e",
5295  D_Total_CL, D_Total_CD, D_Total_CSF, D_Total_CMx, D_Total_CMy, D_Total_CMz, D_Total_CFx, D_Total_CFy,
5296  D_Total_CFz, D_Total_CEff, D_Total_Custom_ObjFunc, D_Total_Heat, D_Total_MaxHeat);
5297  }
5298 
5299  if (aeroelastic) {
5300  for (iMarker_Monitoring = 0; iMarker_Monitoring < config[ZONE_0]->GetnMarker_Monitoring(); iMarker_Monitoring++) {
5301  //Append one by one the surface coeff to aeroelastic coeff. (Think better way do this, maybe use string)
5302  if (iMarker_Monitoring == 0) {
5303  SPRINTF(aeroelastic_coeff, ", %12.10f", aeroelastic_plunge[iMarker_Monitoring]);
5304  }
5305  else {
5306  SPRINTF(surface_coeff, ", %12.10f", aeroelastic_plunge[iMarker_Monitoring]);
5307  strcat(aeroelastic_coeff, surface_coeff);
5308  }
5309  SPRINTF(surface_coeff, ", %12.10f", aeroelastic_pitch[iMarker_Monitoring]);
5310  strcat(aeroelastic_coeff, surface_coeff);
5311  }
5312  }
5313 
5314  if (output_per_surface) {
5315  for (iMarker_Monitoring = 0; iMarker_Monitoring < config[ZONE_0]->GetnMarker_Monitoring(); iMarker_Monitoring++) {
5316  //Append one by one the surface coeff to monitoring coeff. (Think better way do this, maybe use string)
5317  if (iMarker_Monitoring == 0) {
5318  SPRINTF(monitoring_coeff, ", %12.10f", Surface_CL[iMarker_Monitoring]);
5319  }
5320  else {
5321  SPRINTF(surface_coeff, ", %12.10f", Surface_CL[iMarker_Monitoring]);
5322  strcat(monitoring_coeff, surface_coeff);
5323  }
5324  SPRINTF(surface_coeff, ", %12.10f", Surface_CD[iMarker_Monitoring]);
5325  strcat(monitoring_coeff, surface_coeff);
5326  SPRINTF(surface_coeff, ", %12.10f", Surface_CSF[iMarker_Monitoring]);
5327  strcat(monitoring_coeff, surface_coeff);
5328  SPRINTF(surface_coeff, ", %12.10f", Surface_CEff[iMarker_Monitoring]);
5329  strcat(monitoring_coeff, surface_coeff);
5330  SPRINTF(surface_coeff, ", %12.10f", Surface_CFx[iMarker_Monitoring]);
5331  strcat(monitoring_coeff, surface_coeff);
5332  SPRINTF(surface_coeff, ", %12.10f", Surface_CFy[iMarker_Monitoring]);
5333  strcat(monitoring_coeff, surface_coeff);
5334  SPRINTF(surface_coeff, ", %12.10f", Surface_CFz[iMarker_Monitoring]);
5335  strcat(monitoring_coeff, surface_coeff);
5336  SPRINTF(surface_coeff, ", %12.10f", Surface_CMx[iMarker_Monitoring]);
5337  strcat(monitoring_coeff, surface_coeff);
5338  SPRINTF(surface_coeff, ", %12.10f", Surface_CMy[iMarker_Monitoring]);
5339  strcat(monitoring_coeff, surface_coeff);
5340  SPRINTF(surface_coeff, ", %12.10f", Surface_CMz[iMarker_Monitoring]);
5341  strcat(monitoring_coeff, surface_coeff);
5342 
5343  if(buffet){
5344  SPRINTF(surface_coeff, ", %12.10f", Surface_Buffet_Metric[iMarker_Monitoring]);
5345  strcat(monitoring_coeff, surface_coeff);
5346  }
5347  }
5348  }
5349 
5350  if (turbo){
5351  for (iMarker_Monitoring = 0; iMarker_Monitoring < config[ZONE_0]->GetnMarker_TurboPerformance(); iMarker_Monitoring++){
5352  if (iMarker_Monitoring == 0){
5353  SPRINTF(turbo_coeff, ", %12.10f", TotalPressureLoss[iMarker_Monitoring][nSpanWiseSections]);
5354  }else{
5355  SPRINTF(surface_coeff, ", %12.10f", TotalPressureLoss[iMarker_Monitoring][nSpanWiseSections]);
5356  strcat(turbo_coeff, surface_coeff);
5357  }
5358  SPRINTF(surface_coeff, ", %12.10f", KineticEnergyLoss[iMarker_Monitoring][nSpanWiseSections]);
5359  strcat(turbo_coeff, surface_coeff);
5360  SPRINTF(surface_coeff, ", %12.10f", EntropyGen[iMarker_Monitoring][nSpanWiseSections]);
5361  strcat(turbo_coeff, surface_coeff);
5362  SPRINTF(surface_coeff, ", %12.10f", EulerianWork[iMarker_Monitoring][nSpanWiseSections]);
5363  strcat(turbo_coeff, surface_coeff);
5364  SPRINTF(surface_coeff, ", %12.10f", PressureRatio[iMarker_Monitoring][nSpanWiseSections]);
5365  strcat(turbo_coeff, surface_coeff);
5366  SPRINTF(surface_coeff, ", %12.10f", 180.0/PI_NUMBER*FlowAngleIn[iMarker_Monitoring][nSpanWiseSections]);
5367  strcat(turbo_coeff, surface_coeff);
5368  SPRINTF(surface_coeff, ", %12.10f", 180.0/PI_NUMBER*FlowAngleOut[iMarker_Monitoring][nSpanWiseSections]);
5369  strcat(turbo_coeff, surface_coeff);
5370  SPRINTF(surface_coeff, ", %12.10f", 180.0/PI_NUMBER*AbsFlowAngleIn[iMarker_Monitoring][nSpanWiseSections]);
5371  strcat(turbo_coeff, surface_coeff);
5372  SPRINTF(surface_coeff, ", %12.10f", 180.0/PI_NUMBER*AbsFlowAngleOut[iMarker_Monitoring][nSpanWiseSections]);
5373  strcat(turbo_coeff, surface_coeff);
5374  SPRINTF(surface_coeff, ", %12.10f", MassFlowIn[iMarker_Monitoring][nSpanWiseSections]);
5375  strcat(turbo_coeff, surface_coeff);
5376  SPRINTF(surface_coeff, ", %12.10f", MassFlowOut[iMarker_Monitoring][nSpanWiseSections]);
5377  strcat(turbo_coeff, surface_coeff);
5378  SPRINTF(surface_coeff, ", %12.10f", sqrt(MachIn[iMarker_Monitoring][nSpanWiseSections][1]*MachIn[iMarker_Monitoring][nSpanWiseSections][1] + MachIn[iMarker_Monitoring][nSpanWiseSections][0]*MachIn[iMarker_Monitoring][nSpanWiseSections][0]));
5379  strcat(turbo_coeff, surface_coeff);
5380  SPRINTF(surface_coeff, ", %12.10f", sqrt(MachOut[iMarker_Monitoring][nSpanWiseSections][1]*MachOut[iMarker_Monitoring][nSpanWiseSections][1] + MachOut[iMarker_Monitoring][nSpanWiseSections][0]*MachOut[iMarker_Monitoring][nSpanWiseSections][0]));
5381  strcat(turbo_coeff, surface_coeff);
5382  //
5383  SPRINTF(surface_coeff, ", %12.10f", TotalTotalEfficiency[iMarker_Monitoring][nSpanWiseSections]);
5384  strcat(turbo_coeff, surface_coeff);
5385  SPRINTF(surface_coeff, ", %12.10f", TotalStaticEfficiency[iMarker_Monitoring][nSpanWiseSections]);
5386  strcat(turbo_coeff, surface_coeff);
5387 
5388  }
5389  }
5390 
5391 
5392  /*--- Flow residual ---*/
5393  if (nDim == 2) {
5394  if (compressible) SPRINTF (flow_resid, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", log10 (residual_flow[0]), log10 (residual_flow[1]), log10 (residual_flow[2]), log10 (residual_flow[3]), dummy);
5395  if (incompressible) SPRINTF (flow_resid, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", log10 (residual_flow[0]), log10 (residual_flow[1]), log10 (residual_flow[2]), log10 (residual_flow[3]), dummy);
5396  }
5397  else {
5398  if (compressible) SPRINTF (flow_resid, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", log10 (residual_flow[0]), log10 (residual_flow[1]), log10 (residual_flow[2]), log10 (residual_flow[3]), log10 (residual_flow[4]) );
5399  if (incompressible) SPRINTF (flow_resid, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", log10 (residual_flow[0]), log10 (residual_flow[1]), log10 (residual_flow[2]), log10 (residual_flow[3]), log10 (residual_flow[4]));
5400  }
5401 
5402  /*--- Turbulent residual ---*/
5403  if (turbulent) {
5404  switch(nVar_Turb) {
5405  case 1: SPRINTF (turb_resid, ", %12.10f", log10 (residual_turbulent[0])); break;
5406  case 2: SPRINTF (turb_resid, ", %12.10f, %12.10f", log10(residual_turbulent[0]), log10(residual_turbulent[1])); break;
5407  }
5408  }
5409 
5410  /*---- Averaged stagnation pressure at an exit ----*/
5411 
5412  if (output_surface) {
5413  SPRINTF( surface_outputs, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", Surface_MassFlow, Surface_Mach, Surface_Temperature, Surface_Pressure, Surface_Density, Surface_Enthalpy, Surface_NormalVelocity, Surface_Uniformity, Surface_SecondaryStrength, Surface_MomentumDistortion, Surface_SecondOverUniform, Surface_TotalTemperature, Surface_TotalPressure, Surface_PressureDrop);
5414 
5415  if (direct_diff != NO_DERIVATIVE) {
5416  SPRINTF( d_surface_outputs, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e",
5417  D_Surface_Uniformity, D_Surface_SecondaryStrength, D_Surface_MomentumDistortion, D_Surface_SecondOverUniform, D_Surface_PressureDrop);
5418  }
5419  }
5420 
5421  /*--- Transition residual ---*/
5422  if (transition) {
5423  SPRINTF (trans_resid, ", %12.10f, %12.10f", log10(residual_transition[0]), log10(residual_transition[1]));
5424  }
5425 
5426  /*--- Combo objective ---*/
5427  if (output_comboObj) {
5428  SPRINTF(combo_obj,", %12.10f", Total_ComboObj);
5429  }
5430 
5431  /*--- Fluid structure residual ---*/
5432  // if (fluid_structure) {
5433  // if (nDim == 2) SPRINTF (levelset_resid, ", %12.10f, %12.10f, 0.0", log10 (residual_fea[0]), log10 (residual_fea[1]));
5434  // else SPRINTF (levelset_resid, ", %12.10f, %12.10f, %12.10f", log10 (residual_fea[0]), log10 (residual_fea[1]), log10 (residual_fea[2]));
5435  // }
5436 
5437  if (adjoint) {
5438 
5439  /*--- Adjoint coefficients ---*/
5440  if (!turbo) {
5441  if (compressible) {
5442  SPRINTF (adjoint_coeff, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, 0.0", Total_Sens_Geo, Total_Sens_Mach, Total_Sens_AoA, Total_Sens_Press, Total_Sens_Temp);
5443  }
5444  if (incompressible) {
5445  SPRINTF (adjoint_coeff, ", %14.8e, %14.8e, %14.8e, %14.8e", Total_Sens_Geo, Total_Sens_ModVel, Total_Sens_BPressure, Total_Sens_Temp);
5446  }
5447  } else
5448  SPRINTF (adjoint_coeff, ", %14.8e, %14.8e, %14.8e", Total_Sens_Geo, Total_Sens_BPressure, Total_Sens_Temp);
5449 
5450  /*--- Adjoint flow residuals ---*/
5451  if (nDim == 2) {
5452  if (compressible) SPRINTF (adj_flow_resid, ", %14.8e, %14.8e, %14.8e, %14.8e, 0.0", log10 (residual_adjflow[0]), log10 (residual_adjflow[1]), log10 (residual_adjflow[2]), log10 (residual_adjflow[3]) );
5453  if (incompressible) SPRINTF (adj_flow_resid, ", %14.8e, %14.8e, %14.8e, %14.8e, 0.0", log10 (residual_adjflow[0]), log10 (residual_adjflow[1]), log10 (residual_adjflow[2]), log10 (residual_adjflow[3]) );
5454  }
5455  else {
5456  if (compressible) SPRINTF (adj_flow_resid, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", log10 (residual_adjflow[0]), log10 (residual_adjflow[1]), log10 (residual_adjflow[2]), log10 (residual_adjflow[3]), log10 (residual_adjflow[4]) );
5457  if (incompressible) SPRINTF (adj_flow_resid, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", log10 (residual_adjflow[0]), log10 (residual_adjflow[1]), log10 (residual_adjflow[2]), log10 (residual_adjflow[3]), log10 (residual_adjflow[4]));
5458  }
5459 
5460  /*--- Adjoint turbulent residuals ---*/
5461  if (turbulent)
5462  if (!frozen_visc) {
5463  if (nVar_AdjTurb == 1) {
5464  SPRINTF (adj_turb_resid, ", %14.8e", log10 (residual_adjturbulent[0]));
5465  } else if (nVar_AdjTurb > 1) {
5466  SPRINTF (adj_turb_resid, ", %14.8e, %14.8e", log10 (residual_adjturbulent[0]), log10 (residual_adjturbulent[1]));
5467  }
5468  }
5469 
5470  }
5471 
5472  if (weakly_coupled_heat) {
5473  SPRINTF (heat_resid, ", %14.8e", log10 (residual_heat[0]));
5474  }
5475 
5476  break;
5477 
5478  case HEAT_EQUATION_FVM:
5479 
5480  SPRINTF (direct_coeff, ", %14.8e, %14.8e, %14.8e", Total_Heat, Total_MaxHeat, Total_Temperature);
5481  SPRINTF (heat_resid, ", %14.8e", log10 (residual_heat[0]));
5482 
5483  break;
5484 
5485  case FEM_ELASTICITY:
5486 
5487  SPRINTF (begin_fem, ", %14.8e", 0.0);
5488 
5489  if (incload) SPRINTF (fem_coeff, ", %14.8e, %14.8e, %14.8e", Total_VMStress, Total_ForceCoeff, Total_IncLoad);
5490  else SPRINTF (fem_coeff, ", %14.8e, %14.8e", Total_VMStress, Total_ForceCoeff);
5491  /*--- FEM residual ---*/
5492  if (nDim == 2) {
5493  if (linear_analysis) SPRINTF (fem_resid, ", %14.8e, %14.8e, %14.8e", log10 (residual_fem[0]), log10 (residual_fem[1]), dummy);
5494  if (nonlinear_analysis) SPRINTF (fem_resid, ", %14.8e, %14.8e, %14.8e", log10 (residual_fem[0]), log10 (residual_fem[1]), log10 (residual_fem[2]));
5495  }
5496  else {
5497  SPRINTF (fem_resid, ", %14.8e, %14.8e, %14.8e", log10 (residual_fem[0]), log10 (residual_fem[1]), log10 (residual_fem[2]));
5498  }
5499  SPRINTF (end_fem, ", %lu, %12.10f\n", LinSolvIter, timeused/60.0);
5500 
5501  break;
5502 
5503  case DISC_ADJ_FEM:
5504 
5505  SPRINTF (direct_coeff, ", %12.10f", Total_VMStress);
5506  if (nDim == 2) {
5507  SPRINTF (fem_resid, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", log10 (residual_fem[0]), log10 (residual_fem[1]), dummy, dummy, dummy);
5508  }
5509  else {
5510  SPRINTF (fem_resid, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", log10 (residual_fem[0]), log10 (residual_fem[1]), log10 (residual_fem[2]), dummy, dummy);
5511  }
5512 
5513  break;
5514 
5515  }
5516  }
5517  if ((val_iZone == 0 && val_iInst == 0)|| fluid_structure){
5518  /*--- Write the screen header---*/
5519  if ( (!fem && ((write_heads) && !(!DualTime_Iteration && Unsteady))) ||
5520  (fem && ((write_heads_FEM) && !(!DualTime_Iteration && nonlinear_analysis)))
5521  ) {
5522 
5523  if (!fem) {
5524  if (!Unsteady && (config[val_iZone]->GetTime_Marching() != TIME_STEPPING)) {
5525  switch (config[val_iZone]->GetKind_Solver()) {
5526  case EULER : case NAVIER_STOKES: case RANS:
5527  case INC_EULER : case INC_NAVIER_STOKES: case INC_RANS:
5528  case FEM_EULER : case FEM_NAVIER_STOKES: case FEM_RANS: case FEM_LES:
5529  case ADJ_EULER : case ADJ_NAVIER_STOKES: case ADJ_RANS:
5530 
5531  cout << endl << "---------------------- Local Time Stepping Summary ----------------------" << endl;
5532 
5533  for (unsigned short iMesh = FinestMesh; iMesh <= config[val_iZone]->GetnMGLevels(); iMesh++)
5534  cout << "MG level: "<< iMesh << " -> Min. DT: " << solver_container[val_iZone][val_iInst][iMesh][FLOW_SOL]->GetMin_Delta_Time()<<
5535  ". Max. DT: " << solver_container[val_iZone][val_iInst][iMesh][FLOW_SOL]->GetMax_Delta_Time() <<
5536  ". CFL: " << config[val_iZone]->GetCFL(iMesh) << "." << endl;
5537 
5538  if (nZone > 1)
5539  cout << "CFL in zone 2: " << config[1]->GetCFL(MESH_0) << endl;
5540 
5541  cout << "-------------------------------------------------------------------------" << endl;
5542 
5543  if (direct_diff != NO_DERIVATIVE) {
5544  cout << endl << "---------------------- Direct Differentiation Summary -------------------" << endl;
5545  cout << "Coefficients are differentiated with respect to ";
5546  switch (direct_diff) {
5547  case D_MACH:
5548  cout << "Mach number." << endl;
5549  break;
5550  case D_AOA:
5551  cout << "AoA." << endl;
5552  break;
5553  case D_SIDESLIP:
5554  cout << "AoS." << endl;
5555  break;
5556  case D_REYNOLDS:
5557  cout << "Reynolds number." << endl;
5558  break;
5559  case D_TURB2LAM:
5560  cout << "Turb/Lam ratio." << endl;
5561  break;
5562  case D_PRESSURE:
5563  cout << "Freestream Pressure." << endl;
5564  break;
5565  case D_TEMPERATURE:
5566  cout << "Freestream Temperature." << endl;
5567  break;
5568  case D_DENSITY:
5569  cout << "Freestream Density." << endl;
5570  break;
5571  case D_VISCOSITY:
5572  cout << "Freestream Viscosity." << endl;
5573  break;
5574  case D_DESIGN:
5575  cout << "Design Variables." << endl;
5576  break;
5577  default:
5578  break;
5579  }
5580 
5581  cout << " D_CLift(Total)" << " D_CDrag(Total)" << " D_CMz(Total)" <<" D_CEff(Total)" << endl;
5582  cout.width(18); cout << D_Total_CL;
5583  cout.width(18); cout << D_Total_CD;
5584  cout.width(18); cout << D_Total_CMz;
5585  cout.width(18); cout << D_Total_CEff;
5586  cout << endl << "-------------------------------------------------------------------------" << endl;
5587  cout << endl;
5588  }
5589  if (turbo && write_turbo && val_iZone== 0){
5590  WriteTurboPerfConvHistory(config[val_iZone]);
5591  }
5592  break;
5593 
5596 
5597  cout << endl;
5598  cout << "------------------------ Discrete Adjoint Summary -----------------------" << endl;
5599  cout << "Total Geometry Sensitivity (updated every " << config[val_iZone]->GetWrt_Sol_Freq() << " iterations): ";
5600  cout.precision(4);
5601  cout.setf(ios::scientific, ios::floatfield);
5602  cout << Total_Sens_Geo;
5603  cout << endl << "-------------------------------------------------------------------------" << endl;
5604  break;
5605 
5606  }
5607  }
5608  else {
5609  if (flow) {
5610  if ((config[val_iZone]->GetTime_Marching() == TIME_STEPPING) && (config[val_iZone]->GetUnst_CFL()== 0.0))
5611  {
5612  cout << endl << "Min DT: " << solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetMin_Delta_Time()<< ".Max DT: " << solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetMax_Delta_Time() << ".Time step: " << config[val_iZone]->GetDelta_UnstTimeND() << ".";
5613  } else if ((config[val_iZone]->GetTime_Marching() == TIME_STEPPING) && (config[val_iZone]->GetUnst_CFL()!= 0.0)) {
5614  cout << endl << "Min DT: " << solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetMin_Delta_Time()<< ".Max DT: " << solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetMax_Delta_Time() << ". Time step: " << solver_container[val_iZone][val_iInst][config[val_iZone]->GetFinestMesh()][FLOW_SOL]->GetMin_Delta_Time() << ". CFL: " << config[val_iZone]->GetUnst_CFL()<<".";
5615  } else {
5616  cout << endl << "Min DT: " << solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetMin_Delta_Time()<< ".Max DT: " << solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetMax_Delta_Time() << ".Dual Time step: " << config[val_iZone]->GetDelta_UnstTimeND() << ".";
5617  }
5618  } else {
5619  cout << endl << "Dual Time step: " << config[val_iZone]->GetDelta_UnstTimeND() << ".";
5620  }
5621  }
5622  }
5623  else if (fem && !fsi) {
5624  if (dynamic) {
5625  cout << endl << "Simulation time: " << config[val_iZone]->GetCurrent_DynTime() << ". Time step: " << config[val_iZone]->GetDelta_DynTime() << ".";
5626  }
5627  }
5628 
5629  switch (config[val_iZone]->GetKind_Solver()) {
5630  case EULER : case NAVIER_STOKES:
5631  case INC_EULER : case INC_NAVIER_STOKES:
5632  case FEM_EULER : case FEM_NAVIER_STOKES: case FEM_LES:
5633 
5634  /*--- Visualize the maximum residual ---*/
5635  iPointMaxResid = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetPoint_Max(0);
5636  Coord = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetPoint_Max_Coord(0);
5637 
5638  cout << endl << "----------------------- Residual Evolution Summary ----------------------" << endl;
5639 
5640  cout << "log10[Maximum residual]: " << log10(solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetRes_Max(0)) << "." << endl;
5641 
5642  if (config[val_iZone]->GetSystemMeasurements() == SI) {
5643  cout <<"Maximum residual point " << iPointMaxResid << ", located at (" << Coord[0] << ", " << Coord[1];
5644  if (nDim == 3) cout << ", " << Coord[2];
5645  cout << ")." << endl;
5646  }
5647  else {
5648  cout <<"Maximum residual point " << iPointMaxResid << ", located at (" << Coord[0]*12.0 << ", " << Coord[1]*12.0;
5649  if (nDim == 3) cout << ", " << Coord[2]*12.0;
5650  cout << ")." << endl;
5651  }
5652 
5653  /*--- Print out the number of non-physical points and reconstructions ---*/
5654 
5655  if (config[val_iZone]->GetNonphysical_Points() > 0)
5656  cout << "There are " << config[val_iZone]->GetNonphysical_Points() << " non-physical points in the solution." << endl;
5657  if (config[val_iZone]->GetNonphysical_Reconstr() > 0)
5658  cout << "There are " << config[val_iZone]->GetNonphysical_Reconstr() << " non-physical states in the upwind reconstruction." << endl;
5659 
5660  cout << "-------------------------------------------------------------------------" << endl;
5661 
5662  if (!Unsteady) cout << endl << " Iter" << " Time(s)";
5663  else cout << endl << " IntIter" << " ExtIter";
5664 
5665  // if (!fluid_structure) {
5666  if (incompressible && !weakly_coupled_heat) {
5667  if (energy) {cout << " Res[Press]" << " Res[Temp]" << " CLift(Total)" << " CDrag(Total)" << endl;}
5668  else {cout << " Res[Press]" << " Res[Velx]" << " CLift(Total)" << " CDrag(Total)" << endl;}
5669  }
5670  else if (incompressible && weakly_coupled_heat) cout << " Res[Press]" << " Res[Heat]" << " HFlux(Total)";
5671  else if (rotating_frame && nDim == 3 && !turbo) cout << " Res[Rho]" << " Res[RhoE]" << " CThrust(Total)" << " CTorque(Total)" << endl;
5672  else if (aeroelastic) cout << " Res[Rho]" << " Res[RhoE]" << " CLift(Total)" << " CDrag(Total)" << " plunge" << " pitch" << endl;
5673  else if (equiv_area) cout << " Res[Rho]" << " CLift(Total)" << " CDrag(Total)" << " CPress(N-F)" << endl;
5674 
5675  else if (turbo){
5676 
5677  if(nZone < 2){
5678  /*--- single zone output ---*/
5679  cout << " Res[Rho]" << " Res[RhoE]" << " TotPresLoss(%)" << " Entropy Gen.(%)";
5680  }
5681  else{
5682  /* --- multi-zone output ---*/
5683  cout << " Res[Rho]" << " Res[RhoE]" << " TTEfficiency(%)" << " Entropy Gen.(%)";
5684  }
5685  }
5686 
5687  else if (actuator_disk) cout << " Res[Rho]" << " Res[RhoE]" << " CL(Total)" << " CD-CT(Total)";
5688  else if (engine) cout << " Res[Rho]" << " Res[RhoE]" << " CL(Total)" << " CD-CT(Total)";
5689  else cout << " Res[Rho]" << " Res[RhoE]" << " CL(Total)" << " CD(Total)";
5690 
5691  if(extra_heat_output) {
5692  cout << " Res[Heat]" << " HFlux(Total)";
5693  }
5694 
5695  cout << endl;
5696 
5697  break;
5698 
5699  case RANS : case INC_RANS:
5700 
5701  /*--- Visualize the maximum residual ---*/
5702  iPointMaxResid = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetPoint_Max(0);
5703  Coord = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetPoint_Max_Coord(0);
5704 
5705  cout << endl << "----------------------- Residual Evolution Summary ----------------------" << endl;
5706 
5707  cout << "log10[Maximum residual]: " << log10(solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetRes_Max(0)) << "." << endl;
5708  if (config[val_iZone]->GetSystemMeasurements() == SI) {
5709  cout <<"Maximum residual point " << iPointMaxResid << ", located at (" << Coord[0] << ", " << Coord[1];
5710  if (nDim == 3) cout << ", " << Coord[2];
5711  cout << ")." << endl;
5712  }
5713  else {
5714  cout <<"Maximum residual point " << iPointMaxResid << ", located at (" << Coord[0]*12.0 << ", " << Coord[1]*12.0;
5715  if (nDim == 3) cout << ", " << Coord[2]*12.0;
5716  cout << ")." << endl;
5717  }
5718  cout <<"Maximum Omega " << solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetOmega_Max() << ", maximum Strain Rate " << solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetStrainMag_Max() << "." << endl;
5719 
5720  /*--- Print out the number of non-physical points and reconstructions ---*/
5721  if (config[val_iZone]->GetNonphysical_Points() > 0)
5722  cout << "There are " << config[val_iZone]->GetNonphysical_Points() << " non-physical points in the solution." << endl;
5723  if (config[val_iZone]->GetNonphysical_Reconstr() > 0)
5724  cout << "There are " << config[val_iZone]->GetNonphysical_Reconstr() << " non-physical states in the upwind reconstruction." << endl;
5725 
5726  cout << "-------------------------------------------------------------------------" << endl;
5727 
5728  if (!Unsteady) cout << endl << " Iter" << " Time(s)";
5729  else cout << endl << " IntIter" << " ExtIter";
5730  if (incompressible) cout << " Res[Press]";
5731  else cout << " Res[Rho]";//, cout << " Res[RhoE]";
5732 
5733  switch (config[val_iZone]->GetKind_Turb_Model()) {
5734  case SA: case SA_NEG: case SA_E: case SA_E_COMP: case SA_COMP: cout << " Res[nu]"; break;
5735  case SST: case SST_SUST: cout << " Res[kine]" << " Res[omega]"; break;
5736  }
5737 
5738  if (weakly_coupled_heat) {
5739  cout << " Res[Heat]";
5740  }
5741 
5742  if (transition) { cout << " Res[Int]" << " Res[Re]"; }
5743  else if (rotating_frame && nDim == 3 && !turbo ) cout << " CThrust(Total)" << " CTorque(Total)";
5744  else if (aeroelastic) cout << " CLift(Total)" << " CDrag(Total)" << " plunge" << " pitch";
5745  else if (equiv_area) cout << " CLift(Total)" << " CDrag(Total)" << " CPress(N-F)";
5746  else if (turbo){
5747  if (nZone < 2){
5748  /*--- single zone output ---*/
5749  cout << " TotPresLoss(%)" << " Entropy Gen.(%)";
5750  }
5751  else{
5752  /*--- multi zone output ---*/
5753  cout << " TTEfficiency(%)" << " Entropy Gen.(%)";
5754 
5755  }
5756  }
5757  else if (weakly_coupled_heat) {
5758  cout << " HFlux(Total)";
5759  }
5760  else cout << " CLift(Total)" << " CDrag(Total)";
5761 
5762  if(extra_heat_output) {
5763  cout << " Res[Heat]" << " HFlux(Total)";
5764  }
5765 
5766  cout << endl;
5767 
5768  break;
5769 
5770  case HEAT_EQUATION_FVM :
5771  if (!Unsteady) cout << endl << " Iter" << " Time(s)";
5772  else cout << endl << " IntIter" << " ExtIter";
5773 
5774  cout << " Res[Heat]" << " HFlux(Total)";
5775  break;
5776 
5777  case FEM_ELASTICITY :
5778  if (!nonlinear_analysis) cout << endl << " Iter" << " Time(s)";
5779  else cout << endl << " IntIter" << " ExtIter";
5780 
5781  if (linear_analysis) {
5782  if (nDim == 2) cout << " Res[Displx]" << " Res[Disply]" << " VMS(Max)"<< endl;
5783  if (nDim == 3) cout << " Res[Displx]" << " Res[Disply]" << " Res[Displz]" << " VMS(Max)"<< endl;
5784  }
5785  else if (nonlinear_analysis) {
5786  switch (config[val_iZone]->GetResidual_Criteria_FEM()) {
5787  case RESFEM_RELATIVE:
5788  cout << " Res[UTOL]" << " Res[RTOL]" << " Res[ETOL]" << " VMS(Max)"<< endl;
5789  break;
5790  case RESFEM_ABSOLUTE:
5791  cout << " Res[UTOL-A]" << " Res[RTOL-A]" << " Res[ETOL-A]" << " VMS(Max)"<< endl;
5792  break;
5793  default:
5794  cout << " Res[UTOL]" << " Res[RTOL]" << " Res[ETOL]" << " VMS(Max)"<< endl;
5795  break;
5796  }
5797  }
5798  break;
5799 
5800  case ADJ_EULER : case ADJ_NAVIER_STOKES :
5803 
5804  /*--- Visualize the maximum residual ---*/
5805  iPointMaxResid = solver_container[val_iZone][val_iInst][FinestMesh][ADJFLOW_SOL]->GetPoint_Max(0);
5806  Coord = solver_container[val_iZone][val_iInst][FinestMesh][ADJFLOW_SOL]->GetPoint_Max_Coord(0);
5807  cout << endl << "log10[Maximum residual]: " << log10(solver_container[val_iZone][val_iInst][FinestMesh][ADJFLOW_SOL]->GetRes_Max(0)) << "." << endl;
5808  if (config[val_iZone]->GetSystemMeasurements() == SI) {
5809  cout <<"Maximum residual point " << iPointMaxResid << ", located at (" << Coord[0] << ", " << Coord[1];
5810  if (nDim == 3) cout << ", " << Coord[2];
5811  cout << ")." << endl;
5812  }
5813  else {
5814  cout <<"Maximum residual point " << iPointMaxResid << ", located at (" << Coord[0]*12.0 << ", " << Coord[1]*12.0;
5815  if (nDim == 3) cout << ", " << Coord[2]*12.0;
5816  cout << ")." << endl;
5817  }
5818 
5819  /*--- Print out the number of non-physical points and reconstructions ---*/
5820  if (config[val_iZone]->GetNonphysical_Points() > 0)
5821  cout << "There are " << config[val_iZone]->GetNonphysical_Points() << " non-physical points in the solution." << endl;
5822 
5823  if (!Unsteady) cout << endl << " Iter" << " Time(s)";
5824  else cout << endl << " IntIter" << " ExtIter";
5825 
5826  if (incompressible) {
5827  if (energy) {cout << " Res[Psi_Press]" << " Res[Psi_Temp]";}
5828  else {cout << " Res[Psi_Press]" << " Res[Psi_Velx]";}
5829  }
5830  else cout << " Res[Psi_Rho]" << " Res[Psi_E]";
5831  if (disc_adj) {
5832  if (!turbo){
5833  if (compressible) {
5834  cout << " Sens_Press" << " Sens_AoA" << endl;
5835  }
5836  if (incompressible) {
5837  if (energy) {
5838  cout << " Sens_Vin" << " Sens_Temp" << endl;
5839  } else {
5840  cout << " Sens_Vin" << " Sens_Pout" << endl;
5841  }
5842  } } else {
5843  cout << " Sens_PressOut" << " Sens_TotTempIn" << endl;
5844  }
5845  } else {
5846  cout << " Sens_Geo" << " Sens_AoA" << endl;
5847  }
5848  break;
5849 
5850  case ADJ_RANS : case DISC_ADJ_RANS: case DISC_ADJ_INC_RANS:
5851 
5852  /*--- Visualize the maximum residual ---*/
5853  iPointMaxResid = solver_container[val_iZone][val_iInst][FinestMesh][ADJFLOW_SOL]->GetPoint_Max(0);
5854  Coord = solver_container[val_iZone][val_iInst][FinestMesh][ADJFLOW_SOL]->GetPoint_Max_Coord(0);
5855  cout << endl << "log10[Maximum residual]: " << log10(solver_container[val_iZone][val_iInst][FinestMesh][ADJFLOW_SOL]->GetRes_Max(0)) << "." << endl;
5856  if (config[val_iZone]->GetSystemMeasurements() == SI) {
5857  cout <<"Maximum residual point " << iPointMaxResid << ", located at (" << Coord[0] << ", " << Coord[1];
5858  if (nDim == 3) cout << ", " << Coord[2];
5859  cout << ")." << endl;
5860  }
5861  else {
5862  cout <<"Maximum residual point " << iPointMaxResid << ", located at (" << Coord[0]*12.0 << ", " << Coord[1]*12.0;
5863  if (nDim == 3) cout << ", " << Coord[2]*12.0;
5864  cout << ")." << endl;
5865  }
5866 
5867  /*--- Print out the number of non-physical points and reconstructions ---*/
5868  if (config[val_iZone]->GetNonphysical_Points() > 0)
5869  cout << "There are " << config[val_iZone]->GetNonphysical_Points() << " non-physical points in the solution." << endl;
5870 
5871  if (!Unsteady) cout << endl << " Iter" << " Time(s)";
5872  else cout << endl << " IntIter" << " ExtIter";
5873 
5874  if (incompressible) cout << " Res[Psi_Press]";
5875  else cout << " Res[Psi_Rho]";
5876 
5877  if (!frozen_visc) {
5878  cout << " Res[Psi_Turb[0]]";
5879  }
5880  else {
5881  if (incompressible) {if (energy) {cout << " Res[Psi_Temp]";}
5882  else {cout << " Res[Psi_Velx]";}}
5883  else cout << " Res[Psi_E]";
5884  }
5885  if (weakly_coupled_heat) {
5886  cout << " Res[Psi_E]";
5887  }
5888  if (disc_adj) {
5889  if (!turbo){
5890  if (compressible) {
5891  cout << " Sens_Press" << " Sens_AoA" << endl;
5892  }
5893  if (incompressible) {
5894  cout << " Sens_Vin" << " Sens_Pout" << endl;
5895  }
5896  } else {
5897  cout << " Sens_PressOut" << " Sens_TotTempIn" << endl; }
5898  } else {
5899  cout << " Sens_Geo" << " Sens_AoA" << endl;
5900  }
5901  break;
5902 
5903  case DISC_ADJ_FEM :
5904  cout << endl << " IntIter" << " ExtIter";
5905 
5906  if (nDim == 2) cout << " Res[Ux_adj]" << " Res[Uy_adj]" << " Sens[E]" << " Sens[Nu]"<< endl;
5907  if (nDim == 3) cout << " Res[Ux_adj]" << " Res[Uy_adj]" << " Res[Uz_adj]" << " Sens[E]" << " Sens[Nu]"<< endl;
5908 
5909  break;
5910 
5911  }
5912 
5913  }
5914  }
5915 
5916  /*--- Write the solution on the screen ---*/
5917 
5918  if ((val_iZone == 0 && val_iInst == 0)|| fluid_structure){
5919  cout.precision(6);
5920  cout.setf(ios::fixed, ios::floatfield);
5921  if (!fem) {
5922  if (!Unsteady) {
5923  cout.width(5); cout << iExtIter + ExtIter_OffSet;
5924  cout.width(11); cout << timeiter;
5925 
5926  } else if (Unsteady && DualTime_Iteration) {
5927  cout.width(8); cout << iIntIter;
5928  cout.width(8); cout << iExtIter;
5929  }
5930  }
5931  else if (fem) {
5932  if (!DualTime_Iteration) {
5933  if (!nonlinear_analysis) {
5934  cout.width(5); cout << iExtIter;
5935  cout.width(11); cout << timeiter;
5936 
5937  } else {
5938  cout.width(8); cout << iIntIter;
5939  cout.width(8); cout << iExtIter;
5940  }
5941  }
5942  else if (discadj_fem){
5943  cout.width(8); cout << iIntIter;
5944  cout.width(8); cout << iExtIter;
5945  }
5946  }
5947  }
5948 
5949  switch (config[val_iZone]->GetKind_Solver()) {
5950  case EULER : case NAVIER_STOKES:
5951  case INC_EULER : case INC_NAVIER_STOKES:
5952  case FEM_EULER : case FEM_NAVIER_STOKES: case FEM_LES:
5953 
5954  /*--- Write history file ---*/
5955 
5956  if ((!DualTime_Iteration) && (output_files)) {
5957  if (!turbo) {
5958  config[val_iZone]->GetHistFile()[0] << begin << direct_coeff;
5959  if (buffet) config[val_iZone]->GetHistFile()[0] << buffet_coeff;
5960  if (thermal) config[val_iZone]->GetHistFile()[0] << heat_coeff;
5961  if (equiv_area) config[val_iZone]->GetHistFile()[0] << equivalent_area_coeff;
5962  if (engine || actuator_disk) config[val_iZone]->GetHistFile()[0] << engine_coeff;
5963  if (inv_design) {
5964  config[val_iZone]->GetHistFile()[0] << Cp_inverse_design;
5965  if (thermal) config[val_iZone]->GetHistFile()[0] << Heat_inverse_design;
5966  }
5967  if (rotating_frame && !turbo) config[val_iZone]->GetHistFile()[0] << rotating_frame_coeff;
5968  config[val_iZone]->GetHistFile()[0] << flow_resid;
5969  if (weakly_coupled_heat) config[val_iZone]->GetHistFile()[0] << heat_resid;
5970  }
5971  else {
5972  config[val_iZone]->GetHistFile()[0] << begin << turbo_coeff << flow_resid;
5973  }
5974 
5975  if (aeroelastic) config[val_iZone]->GetHistFile()[0] << aeroelastic_coeff;
5976  if (output_per_surface) config[val_iZone]->GetHistFile()[0] << monitoring_coeff;
5977  if (output_surface) config[val_iZone]->GetHistFile()[0] << surface_outputs;
5978  if (direct_diff != NO_DERIVATIVE) {
5979  config[val_iZone]->GetHistFile()[0] << d_direct_coeff;
5980  if (output_surface) config[val_iZone]->GetHistFile()[0] << d_surface_outputs;
5981  }
5982  if (output_comboObj) config[val_iZone]->GetHistFile()[0] << combo_obj;
5983  config[val_iZone]->GetHistFile()[0] << end;
5984  config[val_iZone]->GetHistFile()[0].flush();
5985  }
5986 
5987  /*--- Write screen output ---*/
5988  if ((val_iZone == 0 && val_iInst == 0)|| fluid_structure){
5989  if(DualTime_Iteration || !Unsteady) {
5990  cout.precision(6);
5991  cout.setf(ios::fixed, ios::floatfield);
5992  cout.width(13); cout << log10(residual_flow[0]);
5993  if (!equiv_area) {
5994  if (compressible) {
5995  if (nDim == 2 ) { cout.width(14); cout << log10(residual_flow[3]); }
5996  else { cout.width(14); cout << log10(residual_flow[4]); }
5997  }
5998  if (incompressible && !weakly_coupled_heat) {
5999  if (energy) {cout.width(14); cout << log10(residual_flow[nDim+1]);}
6000  else {cout.width(14); cout << log10(residual_flow[1]);}
6001  }
6002  if (incompressible && weakly_coupled_heat) { cout.width(14); cout << log10(residual_heat[0]);}
6003 
6004  }
6005 
6006  if (rotating_frame && nDim == 3 && !turbo ) {
6007  cout.setf(ios::scientific, ios::floatfield);
6008  cout.width(15); cout << Total_CT;
6009  cout.width(15); cout << Total_CQ;
6010  cout.unsetf(ios_base::floatfield);
6011  }
6012  else if (equiv_area) { cout.width(15); cout << min(10000.0, max(-10000.0, Total_CL)); cout.width(15); cout << min(10000.0, max(-10000.0, Total_CD)); cout.width(15);
6013  cout.precision(4);
6014  cout.setf(ios::scientific, ios::floatfield);
6015  cout << Total_CNearFieldOF; }
6016  else if (turbo) {
6017  cout.setf(ios::scientific, ios::floatfield);
6018 
6019  if (nZone < 2) {
6020  cout.width(15); cout << TotalPressureLoss[0][nSpanWiseSections]*100.0;
6021  cout.width(15); cout << EntropyGen[0][nSpanWiseSections]*100.0;
6022  }
6023  else {
6024  cout.width(15); cout << TotalTotalEfficiency[nTurboPerf -1][nSpanWiseSections]*100.0;
6025  cout.width(15); cout << EntropyGen[nTurboPerf -1][nSpanWiseSections]*100.0;
6026  }
6027 
6028  cout.unsetf(ios_base::floatfield);
6029 
6030  }
6031  else if (weakly_coupled_heat) { cout.width(14); cout << log10(Total_Heat); }
6032  else { cout.width(15); cout << min(10000.0, max(-10000.0, Total_CL)); cout.width(15); cout << min(10000.0, max(-10000.0, Total_CD)); }
6033  if (aeroelastic) {
6034  cout.setf(ios::scientific, ios::floatfield);
6035  cout.width(15); cout << aeroelastic_plunge[0]; //Only output the first marker being monitored to the console.
6036  cout.width(15); cout << aeroelastic_pitch[0];
6037  cout.unsetf(ios_base::floatfield);
6038  }
6039 
6040  if (extra_heat_output) { cout.width(15); cout << Extra_Heat_Residual; cout.width(15); cout << Extra_Total_Heat; }
6041  cout << endl;
6042 
6043  }
6044  }
6045  break;
6046 
6047  case RANS : case INC_RANS:
6048 
6049  /*--- Write history file ---*/
6050 
6051  if ((!DualTime_Iteration) && (output_files)) {
6052 
6053  if (!turbo) {
6054  config[val_iZone]->GetHistFile()[0] << begin << direct_coeff;
6055  if (buffet) config[val_iZone]->GetHistFile()[0] << buffet_coeff;
6056  if (thermal) config[val_iZone]->GetHistFile()[0] << heat_coeff;
6057  if (equiv_area) config[val_iZone]->GetHistFile()[0] << equivalent_area_coeff;
6058  if (engine || actuator_disk) config[val_iZone]->GetHistFile()[0] << engine_coeff;
6059  if (inv_design) {
6060  config[val_iZone]->GetHistFile()[0] << Cp_inverse_design;
6061  if (thermal) config[val_iZone]->GetHistFile()[0] << Heat_inverse_design;
6062  }
6063  if (rotating_frame && !turbo) config[val_iZone]->GetHistFile()[0] << rotating_frame_coeff;
6064  config[val_iZone]->GetHistFile()[0] << flow_resid << turb_resid;
6065  if (weakly_coupled_heat) config[val_iZone]->GetHistFile()[0] << heat_resid;
6066  }
6067  else {
6068  config[val_iZone]->GetHistFile()[0] << begin << turbo_coeff << flow_resid << turb_resid;
6069  }
6070 
6071  if (aeroelastic) config[val_iZone]->GetHistFile()[0] << aeroelastic_coeff;
6072  if (output_per_surface) config[val_iZone]->GetHistFile()[0] << monitoring_coeff;
6073  if (output_surface) config[val_iZone]->GetHistFile()[0] << surface_outputs;
6074  if (direct_diff != NO_DERIVATIVE) {
6075  config[val_iZone]->GetHistFile()[0] << d_direct_coeff;
6076  if (output_surface) config[val_iZone]->GetHistFile()[0] << d_surface_outputs;
6077  }
6078  if (output_comboObj) config[val_iZone]->GetHistFile()[0] << combo_obj;
6079  config[val_iZone]->GetHistFile()[0] << end;
6080  config[val_iZone]->GetHistFile()[0].flush();
6081  }
6082 
6083  /*--- Write screen output ---*/
6084 
6085  if ((val_iZone == 0 && val_iInst == 0)|| fluid_structure){
6086  if(DualTime_Iteration || !Unsteady) {
6087  cout.precision(6);
6088  cout.setf(ios::fixed, ios::floatfield);
6089 
6090  if (incompressible) cout.width(13);
6091  else cout.width(14);
6092  cout << log10(residual_flow[0]);
6093  switch(nVar_Turb) {
6094  case 1: cout.width(14); cout << log10(residual_turbulent[0]); break;
6095  case 2: cout.width(14); cout << log10(residual_turbulent[0]);
6096  cout.width(15); cout << log10(residual_turbulent[1]); break;
6097  }
6098 
6099  if (weakly_coupled_heat) {
6100  cout.width(14); cout << log10(residual_heat[0]);
6101  }
6102 
6103  if (transition) { cout.width(14); cout << log10(residual_transition[0]); cout.width(14); cout << log10(residual_transition[1]); }
6104 
6105  if (rotating_frame && nDim == 3 && !turbo ) {
6106  cout.setf(ios::scientific, ios::floatfield);
6107  cout.width(15); cout << Total_CT; cout.width(15);
6108  cout << Total_CQ;
6109  cout.unsetf(ios_base::floatfield);
6110  }
6111  else if (equiv_area) { cout.width(15); cout << min(10000.0, max(-10000.0, Total_CL)); cout.width(15); cout << min(10000.0, max(-10000.0, Total_CD)); cout.width(15);
6112  cout.precision(4);
6113  cout.setf(ios::scientific, ios::floatfield);
6114  cout << Total_CNearFieldOF; }
6115  else if (turbo) {
6116  cout.setf(ios::scientific, ios::floatfield);
6117  if (nZone < 2){
6118  /*--- single zone output ---*/
6119  cout.width(15); cout << TotalPressureLoss[0][nSpanWiseSections]*100.0;
6120  cout.width(15); cout << EntropyGen[0][nSpanWiseSections]*100.0;
6121  }
6122  else{
6123  /*--- multi zone output ---*/
6124  cout.width(15); cout << TotalTotalEfficiency[nTurboPerf - 1][nSpanWiseSections]*100.0;
6125  cout.width(15); cout << EntropyGen[nTurboPerf -1][nSpanWiseSections]*100.0;
6126  if (direct_diff){
6127  cout.width(15); cout << D_EntropyGen;
6128  }
6129  }
6130  cout.unsetf(ios_base::floatfield);
6131  }
6132  else if (weakly_coupled_heat) { cout.width(15); cout << Total_Heat; }
6133  else { cout.width(15); cout << min(10000.0, max(-10000.0, Total_CL)); cout.width(15); cout << min(10000.0, max(-10000.0, Total_CD)); }
6134 
6135  if (aeroelastic) {
6136  cout.setf(ios::scientific, ios::floatfield);
6137  cout.width(15); cout << aeroelastic_plunge[0]; //Only output the first marker being monitored to the console.
6138  cout.width(15); cout << aeroelastic_pitch[0];
6139  cout.unsetf(ios_base::floatfield);
6140  }
6141 
6142  if (extra_heat_output) { cout.width(15); cout << Extra_Heat_Residual; cout.width(15); cout << Extra_Total_Heat; }
6143  cout << endl;
6144  }
6145  }
6146  break;
6147 
6148 
6149  case HEAT_EQUATION_FVM:
6150 
6151  if (!DualTime_Iteration) {
6152  config[val_iZone]->GetHistFile()[0] << begin << direct_coeff << heat_resid << end;
6153  config[val_iZone]->GetHistFile()[0].flush();
6154  }
6155  break;
6156 
6157  case FEM_ELASTICITY:
6158 
6159  if (!DualTime_Iteration) {
6160  config[val_iZone]->GetHistFile()[0] << begin << fem_coeff << fem_resid << end_fem;
6161  config[val_iZone]->GetHistFile()[0].flush();
6162 
6163  cout.precision(6);
6164  cout.setf(ios::fixed, ios::floatfield);
6165  if (linear_analysis) {
6166  cout.width(14); cout << log10(residual_fem[0]);
6167  cout.width(14); cout << log10(residual_fem[1]);
6168  if (nDim == 3) { cout.width(14); cout << log10(residual_fem[2]); }
6169  }
6170  else if (nonlinear_analysis) {
6171  cout.width(14); cout << log10(residual_fem[0]);
6172  cout.width(14); cout << log10(residual_fem[1]);
6173  cout.width(14); cout << log10(residual_fem[2]);
6174  }
6175 
6176  cout.precision(4);
6177  cout.setf(ios::scientific, ios::floatfield);
6178  cout.width(14); cout << Total_VMStress;
6179  cout << endl;
6180  }
6181  break;
6182 
6183  case DISC_ADJ_FEM:
6184 
6185  cout.precision(6);
6186  cout.setf(ios::fixed, ios::floatfield);
6187 
6188  cout.width(15); cout << log10(residual_fem[0]);
6189  cout.width(15); cout << log10(residual_fem[1]);
6190  if (nDim == 3) { cout.width(15); cout << log10(residual_fem[2]); }
6191 
6192  cout.precision(4);
6193  cout.setf(ios::scientific, ios::floatfield);
6194 
6195 
6196  if (config[val_iZone]->GetnElasticityMod() == 1){
6197  cout.width(14); cout << solver_container[val_iZone][val_iInst][FinestMesh][ADJFEA_SOL]->GetGlobal_Sens_E(0);
6198  cout.width(14); cout << solver_container[val_iZone][val_iInst][FinestMesh][ADJFEA_SOL]->GetGlobal_Sens_Nu(0);
6199  }
6200  else{
6201  Total_SensE = 0.0; Total_SensNu = 0.0;
6202  for (unsigned short iVar = 0; iVar < config[val_iZone]->GetnElasticityMod(); iVar++){
6203  Total_SensE += solver_container[val_iZone][val_iInst][FinestMesh][ADJFEA_SOL]->GetGlobal_Sens_E(0)
6204  *solver_container[val_iZone][val_iInst][FinestMesh][ADJFEA_SOL]->GetGlobal_Sens_E(0);
6205  Total_SensNu += solver_container[val_iZone][val_iInst][FinestMesh][ADJFEA_SOL]->GetGlobal_Sens_Nu(0)
6206  *solver_container[val_iZone][val_iInst][FinestMesh][ADJFEA_SOL]->GetGlobal_Sens_Nu(0);
6207  }
6208  Total_SensE = sqrt(Total_SensE);
6209  Total_SensNu = sqrt(Total_SensNu);
6210  cout.width(14); cout << Total_SensE;
6211  cout.width(14); cout << Total_SensNu;
6212  }
6213 
6214  cout << endl;
6215  break;
6216 
6217  case ADJ_EULER : case ADJ_NAVIER_STOKES :
6220 
6221  if (!DualTime_Iteration) {
6222  config[val_iZone]->GetHistFile()[0] << begin << adjoint_coeff << adj_flow_resid << end;
6223  config[val_iZone]->GetHistFile()[0].flush();
6224  }
6225  if ((val_iZone == 0 && val_iInst == 0)|| fluid_structure){
6226  if (DualTime_Iteration || !Unsteady){
6227  cout.precision(6);
6228  cout.setf(ios::fixed, ios::floatfield);
6229  if (compressible) {
6230  cout.width(15); cout << log10(residual_adjflow[0]);
6231  cout.width(15); cout << log10(residual_adjflow[nDim+1]);
6232  }
6233  if (incompressible) {
6234  cout.width(17); cout << log10(residual_adjflow[0]);
6235  if (energy) {cout.width(16); cout << log10(residual_adjflow[nDim+1]);}
6236  else {cout.width(16); cout << log10(residual_adjflow[1]);}
6237  }
6238 
6239  if (disc_adj) {
6240  cout.precision(4);
6241  cout.setf(ios::scientific, ios::floatfield);
6242  if (!turbo){
6243  if (compressible) {
6244  cout.width(14); cout << Total_Sens_Press;
6245  cout.width(14); cout << Total_Sens_AoA;
6246  }
6247  if (incompressible) {
6248  cout.width(14); cout << Total_Sens_ModVel;
6249  if (energy) {
6250  cout.width(14); cout << Total_Sens_Temp;
6251  } else {
6252  cout.width(14); cout << Total_Sens_BPressure;
6253  }
6254  }
6255  } else {
6256  cout.width(14); cout << Total_Sens_BPressure;
6257  cout.width(15); cout << Total_Sens_Temp;
6258  }
6259  }else {
6260  cout.precision(4);
6261  cout.setf(ios::scientific, ios::floatfield);
6262  cout.width(14); cout << Total_Sens_Geo;
6263  cout.width(14); cout << Total_Sens_AoA;
6264  }
6265  cout << endl;
6266  cout.unsetf(ios_base::floatfield);
6267  }
6268  }
6269  break;
6270 
6271  case ADJ_RANS : case DISC_ADJ_RANS: case DISC_ADJ_INC_RANS:
6272 
6273  if (!DualTime_Iteration) {
6274  config[val_iZone]->GetHistFile()[0] << begin << adjoint_coeff << adj_flow_resid;
6275  if (!frozen_visc)
6276  config[val_iZone]->GetHistFile()[0] << adj_turb_resid;
6277  config[val_iZone]->GetHistFile()[0] << end;
6278  config[val_iZone]->GetHistFile()[0].flush();
6279  }
6280  if ((val_iZone == 0 && val_iInst == 0)|| fluid_structure){
6281  if (DualTime_Iteration || !Unsteady){
6282  cout.precision(6);
6283  cout.setf(ios::fixed, ios::floatfield);
6284  cout.width(17); cout << log10(residual_adjflow[0]);
6285  if (!frozen_visc) {
6286  cout.width(17); cout << log10(residual_adjturbulent[0]);
6287  }
6288  else {
6289  if (compressible) {
6290  if (geometry[val_iZone][val_iInst][FinestMesh]->GetnDim() == 2 ) { cout.width(15); cout << log10(residual_adjflow[3]); }
6291  else { cout.width(15); cout << log10(residual_adjflow[4]); }
6292  }
6293  if (incompressible) {
6294  if (energy) {cout.width(15); cout << log10(residual_adjflow[nDim+1]);}
6295  else {cout.width(15); cout << log10(residual_adjflow[1]);}
6296  }
6297  }
6298  if (weakly_coupled_heat) {
6299  cout.width(17); cout << log10(residual_adjheat[0]);
6300  }
6301  if (disc_adj) {
6302  if (!turbo){
6303  if (compressible) {
6304  cout.width(14); cout << Total_Sens_Press;
6305  cout.width(14); cout << Total_Sens_AoA;
6306  }
6307  if (incompressible) {
6308  cout.width(14); cout << Total_Sens_ModVel;
6309  if (energy) {
6310  cout.width(14); cout << Total_Sens_Temp;
6311  } else {
6312  cout.width(14); cout << Total_Sens_BPressure;
6313  } }
6314  } else {
6315  cout.width(14); cout << Total_Sens_BPressure;
6316  cout.width(15); cout << Total_Sens_Temp;
6317  }
6318  }else {
6319  cout.precision(4);
6320  cout.setf(ios::scientific, ios::floatfield);
6321  cout.width(14); cout << Total_Sens_Geo;
6322  cout.width(14); cout << Total_Sens_AoA;
6323  }
6324  cout << endl;
6325  cout.unsetf(ios_base::floatfield);
6326  }
6327  }
6328  break;
6329 
6330  }
6331  cout.unsetf(ios::fixed);
6332 
6333  }
6334 
6335 
6336  delete [] residual_flow;
6337  delete [] residual_turbulent;
6338  delete [] residual_transition;
6339  delete [] residual_fea;
6340  delete [] residual_fem;
6341  delete [] residual_heat;
6342 
6343  delete [] residual_adjflow;
6344  delete [] residual_adjturbulent;
6345 
6346  delete [] Surface_CL;
6347  delete [] Surface_CD;
6348  delete [] Surface_CSF;
6349  delete [] Surface_CEff;
6350  delete [] Surface_CFx;
6351  delete [] Surface_CFy;
6352  delete [] Surface_CFz;
6353  delete [] Surface_CMx;
6354  delete [] Surface_CMy;
6355  delete [] Surface_CMz;
6356  delete [] aeroelastic_pitch;
6357  delete [] aeroelastic_plunge;
6358 
6359  }
6360 }
6361 
6362 void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry ****geometry, CConfig **config, unsigned short val_iZone, bool output) {
6363 
6364  char cstr[200];
6365  unsigned short iDim, iMarker_Monitoring;
6366  ofstream Breakdown_file;
6367 
6368  bool compressible = (config[val_iZone]->GetKind_Regime() == COMPRESSIBLE);
6369  bool incompressible = (config[val_iZone]->GetKind_Regime() == INCOMPRESSIBLE);
6370  bool unsteady = (config[val_iZone]->GetTime_Marching() != NO);
6371  bool viscous = config[val_iZone]->GetViscous();
6372  bool dynamic_grid = config[val_iZone]->GetDynamic_Grid();
6373  bool gravity = config[val_iZone]->GetGravityForce();
6374  bool turbulent = config[val_iZone]->GetKind_Solver() == RANS;
6375  bool fixed_cl = config[val_iZone]->GetFixed_CL_Mode();
6376  unsigned short Kind_Solver = config[val_iZone]->GetKind_Solver();
6377  unsigned short Kind_Turb_Model = config[val_iZone]->GetKind_Turb_Model();
6378  unsigned short Ref_NonDim = config[val_iZone]->GetRef_NonDim();
6379 
6380  unsigned short FinestMesh = config[val_iZone]->GetFinestMesh();
6381  unsigned short nDim = geometry[val_iZone][INST_0][FinestMesh]->GetnDim();
6382  bool flow = ((config[val_iZone]->GetKind_Solver() == EULER) ||
6383  (config[val_iZone]->GetKind_Solver() == NAVIER_STOKES) ||
6384  (config[val_iZone]->GetKind_Solver() == RANS) ||
6385  (config[val_iZone]->GetKind_Solver() == INC_EULER) ||
6386  (config[val_iZone]->GetKind_Solver() == INC_NAVIER_STOKES) ||
6387  (config[val_iZone]->GetKind_Solver() == INC_RANS));
6388 
6389  /*--- Output the mean flow solution using only the master node ---*/
6390 
6391  if ((rank == MASTER_NODE) && (flow) && (output)) {
6392 
6393  cout << endl << "Writing the forces breakdown file ("<< config[val_iZone]->GetBreakdown_FileName() << ")." << endl;
6394 
6395  /*--- Initialize variables to store information from all domains (direct solution) ---*/
6396 
6397  su2double Total_CL = 0.0, Total_CD = 0.0, Total_CSF = 0.0,
6398  Total_CMx = 0.0, Total_CMy = 0.0, Total_CMz = 0.0, Total_CEff = 0.0,
6399  Total_CoPx = 0.0, Total_CoPy = 0.0, Total_CoPz = 0.0,
6400  Total_CFx = 0.0, Total_CFy = 0.0, Total_CFz = 0.0, Inv_CL = 0.0,
6401  Inv_CD = 0.0, Inv_CSF = 0.0, Inv_CMx = 0.0, Inv_CMy = 0.0,
6402  Inv_CMz = 0.0, Inv_CEff = 0.0, Inv_CFx = 0.0, Inv_CFy = 0.0, Inv_CFz =
6403  0.0, Mnt_CL = 0.0,
6404  Mnt_CD = 0.0, Mnt_CSF = 0.0, Mnt_CMx = 0.0, Mnt_CMy = 0.0,
6405  Mnt_CMz = 0.0, Mnt_CEff = 0.0, Mnt_CFx = 0.0, Mnt_CFy = 0.0, Mnt_CFz =
6406  0.0, Visc_CL = 0.0,
6407  Visc_CD = 0.0, Visc_CSF = 0.0, Visc_CMx = 0.0, Visc_CMy = 0.0,
6408  Visc_CMz = 0.0, Visc_CEff = 0.0, Visc_CFx = 0.0, Visc_CFy = 0.0, Visc_CFz =
6409  0.0, *Surface_CL = NULL, *Surface_CD = NULL,
6410  *Surface_CSF = NULL, *Surface_CEff = NULL, *Surface_CFx = NULL,
6411  *Surface_CFy = NULL, *Surface_CFz = NULL,
6412  *Surface_CMx = NULL, *Surface_CMy = NULL, *Surface_CMz = NULL,
6413  *Surface_CL_Inv = NULL,
6414  *Surface_CD_Inv = NULL, *Surface_CSF_Inv = NULL,
6415  *Surface_CEff_Inv = NULL, *Surface_CFx_Inv = NULL, *Surface_CFy_Inv =
6416  NULL, *Surface_CFz_Inv = NULL, *Surface_CMx_Inv = NULL,
6417  *Surface_CMy_Inv = NULL, *Surface_CMz_Inv = NULL,
6418  *Surface_CL_Visc = NULL,
6419  *Surface_CD_Visc = NULL, *Surface_CSF_Visc = NULL,
6420  *Surface_CEff_Visc = NULL, *Surface_CFx_Visc = NULL, *Surface_CFy_Visc =
6421  NULL, *Surface_CFz_Visc = NULL, *Surface_CMx_Visc = NULL,
6422  *Surface_CMy_Visc = NULL, *Surface_CMz_Visc = NULL,
6423  *Surface_CL_Mnt = NULL,
6424  *Surface_CD_Mnt = NULL, *Surface_CSF_Mnt = NULL,
6425  *Surface_CEff_Mnt = NULL, *Surface_CFx_Mnt = NULL, *Surface_CFy_Mnt =
6426  NULL, *Surface_CFz_Mnt = NULL, *Surface_CMx_Mnt = NULL,
6427  *Surface_CMy_Mnt = NULL, *Surface_CMz_Mnt = NULL;
6428 
6429  /*--- WARNING: when compiling on Windows, ctime() is not available. Comment out
6430  the two lines below that use the dt variable. ---*/
6431  //time_t now = time(0);
6432  //string dt = ctime(&now); dt[24] = '.';
6433 
6434  /*--- Allocate memory for the coefficients being monitored ---*/
6435 
6436  Surface_CL = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6437  Surface_CD = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6438  Surface_CSF = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6439  Surface_CEff = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6440  Surface_CFx = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6441  Surface_CFy = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6442  Surface_CFz = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6443  Surface_CMx = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6444  Surface_CMy = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6445  Surface_CMz = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6446 
6447  Surface_CL_Inv = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6448  Surface_CD_Inv = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6449  Surface_CSF_Inv = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6450  Surface_CEff_Inv = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6451  Surface_CFx_Inv = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6452  Surface_CFy_Inv = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6453  Surface_CFz_Inv = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6454  Surface_CMx_Inv = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6455  Surface_CMy_Inv = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6456  Surface_CMz_Inv = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6457 
6458  Surface_CL_Visc = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6459  Surface_CD_Visc = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6460  Surface_CSF_Visc =
6461  new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6462  Surface_CEff_Visc = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6463  Surface_CFx_Visc = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6464  Surface_CFy_Visc = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6465  Surface_CFz_Visc = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6466  Surface_CMx_Visc = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6467  Surface_CMy_Visc = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6468  Surface_CMz_Visc = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6469 
6470 
6471  Surface_CL_Mnt = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6472  Surface_CD_Mnt = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6473  Surface_CSF_Mnt =
6474  new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6475  Surface_CEff_Mnt = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6476  Surface_CFx_Mnt = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6477  Surface_CFy_Mnt = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6478  Surface_CFz_Mnt = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6479  Surface_CMx_Mnt = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6480  Surface_CMy_Mnt = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6481  Surface_CMz_Mnt = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6482 
6483  /*--- Flow solution coefficients ---*/
6484 
6485  Total_CL = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CL();
6486  Total_CD = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CD();
6487  Total_CSF = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CSF();
6488  Total_CEff = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CEff();
6489  Total_CMx = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CMx();
6490  Total_CMy = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CMy();
6491  Total_CMz = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CMz();
6492  Total_CFx = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CFx();
6493  Total_CFy = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CFy();
6494  Total_CFz = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CFz();
6495 
6496  if (nDim == 2) {
6497  Total_CoPx = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CoPx() / solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CFy();
6498  Total_CoPy = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CoPy() / solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CFx();
6499  Total_CoPz = 0.0;
6500  }
6501  if (nDim == 3) {
6502  Total_CoPx = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CoPx() / solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CFz();
6503  Total_CoPy = 0.0;
6504  Total_CoPz = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CoPz() / solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CFx();
6505  }
6506 
6507  if (config[ZONE_0]->GetSystemMeasurements() == US) { Total_CoPx *= 12.0; Total_CoPy *= 12.0; Total_CoPz *= 12.0; }
6508 
6509  /*--- Flow inviscid solution coefficients ---*/
6510 
6511  Inv_CL =
6512  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CL_Inv();
6513  Inv_CD =
6514  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CD_Inv();
6515  Inv_CSF =
6516  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CSF_Inv();
6517  Inv_CEff =
6518  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CEff_Inv();
6519  Inv_CMx =
6520  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CMx_Inv();
6521  Inv_CMy =
6522  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CMy_Inv();
6523  Inv_CMz =
6524  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CMz_Inv();
6525  Inv_CFx =
6526  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CFx_Inv();
6527  Inv_CFy =
6528  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CFy_Inv();
6529  Inv_CFz =
6530  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CFz_Inv();
6531 
6532  /*--- Flow viscous solution coefficients ---*/
6533 
6534  Visc_CL =
6535  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CL_Visc();
6536  Visc_CD =
6537  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CD_Visc();
6538  Visc_CSF =
6539  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CSF_Visc();
6540  Visc_CEff =
6541  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CEff_Visc();
6542  Visc_CMx =
6543  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CMx_Visc();
6544  Visc_CMy =
6545  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CMy_Visc();
6546  Visc_CMz =
6547  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CMz_Visc();
6548  Visc_CFx =
6549  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CFx_Visc();
6550  Visc_CFy =
6551  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CFy_Visc();
6552  Visc_CFz =
6553  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CFz_Visc();
6554 
6555  /*--- Flow momentum solution coefficients ---*/
6556 
6557  Mnt_CL =
6558  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CL_Mnt();
6559  Mnt_CD =
6560  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CD_Mnt();
6561  Mnt_CSF =
6562  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CSF_Mnt();
6563  Mnt_CEff =
6564  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CEff_Mnt();
6565  Mnt_CMx =
6566  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CMx_Mnt();
6567  Mnt_CMy =
6568  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CMy_Mnt();
6569  Mnt_CMz =
6570  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CMz_Mnt();
6571  Mnt_CFx =
6572  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CFx_Mnt();
6573  Mnt_CFy =
6574  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CFy_Mnt();
6575  Mnt_CFz =
6576  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CFz_Mnt();
6577 
6578 
6579  /*--- Look over the markers being monitored and get the desired values ---*/
6580 
6581  for (iMarker_Monitoring = 0;
6582  iMarker_Monitoring < config[ZONE_0]->GetnMarker_Monitoring();
6583  iMarker_Monitoring++) {
6584  Surface_CL[iMarker_Monitoring] =
6585  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CL(
6586  iMarker_Monitoring);
6587  Surface_CD[iMarker_Monitoring] =
6588  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CD(
6589  iMarker_Monitoring);
6590  Surface_CSF[iMarker_Monitoring] =
6591  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CSF(
6592  iMarker_Monitoring);
6593  Surface_CEff[iMarker_Monitoring] =
6594  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CEff(
6595  iMarker_Monitoring);
6596  Surface_CMx[iMarker_Monitoring] =
6597  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CMx(
6598  iMarker_Monitoring);
6599  Surface_CMy[iMarker_Monitoring] =
6600  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CMy(
6601  iMarker_Monitoring);
6602  Surface_CMz[iMarker_Monitoring] =
6603  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CMz(
6604  iMarker_Monitoring);
6605  Surface_CFx[iMarker_Monitoring] =
6606  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CFx(
6607  iMarker_Monitoring);
6608  Surface_CFy[iMarker_Monitoring] =
6609  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CFy(
6610  iMarker_Monitoring);
6611  Surface_CFz[iMarker_Monitoring] =
6612  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CFz(
6613  iMarker_Monitoring);
6614 
6615  Surface_CL_Inv[iMarker_Monitoring] =
6616  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CL_Inv(
6617  iMarker_Monitoring);
6618  Surface_CD_Inv[iMarker_Monitoring] =
6619  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CD_Inv(
6620  iMarker_Monitoring);
6621  Surface_CSF_Inv[iMarker_Monitoring] =
6622  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CSF_Inv(
6623  iMarker_Monitoring);
6624  Surface_CEff_Inv[iMarker_Monitoring] =
6625  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CEff_Inv(
6626  iMarker_Monitoring);
6627  Surface_CMx_Inv[iMarker_Monitoring] =
6628  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CMx_Inv(
6629  iMarker_Monitoring);
6630  Surface_CMy_Inv[iMarker_Monitoring] =
6631  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CMy_Inv(
6632  iMarker_Monitoring);
6633  Surface_CMz_Inv[iMarker_Monitoring] =
6634  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CMz_Inv(
6635  iMarker_Monitoring);
6636  Surface_CFx_Inv[iMarker_Monitoring] =
6637  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CFx_Inv(
6638  iMarker_Monitoring);
6639  Surface_CFy_Inv[iMarker_Monitoring] =
6640  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CFy_Inv(
6641  iMarker_Monitoring);
6642  Surface_CFz_Inv[iMarker_Monitoring] =
6643  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CFz_Inv(
6644  iMarker_Monitoring);
6645  Surface_CL_Visc[iMarker_Monitoring] =
6646  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CL_Visc(
6647  iMarker_Monitoring);
6648  Surface_CD_Visc[iMarker_Monitoring] =
6649  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CD_Visc(
6650  iMarker_Monitoring);
6651  Surface_CSF_Visc[iMarker_Monitoring] =
6652  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CSF_Visc(
6653  iMarker_Monitoring);
6654  Surface_CEff_Visc[iMarker_Monitoring] =
6655  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CEff_Visc(
6656  iMarker_Monitoring);
6657  Surface_CMx_Visc[iMarker_Monitoring] =
6658  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CMx_Visc(
6659  iMarker_Monitoring);
6660  Surface_CMy_Visc[iMarker_Monitoring] =
6661  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CMy_Visc(
6662  iMarker_Monitoring);
6663  Surface_CMz_Visc[iMarker_Monitoring] =
6664  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CMz_Visc(
6665  iMarker_Monitoring);
6666  Surface_CFx_Visc[iMarker_Monitoring] =
6667  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CFx_Visc(
6668  iMarker_Monitoring);
6669  Surface_CFy_Visc[iMarker_Monitoring] =
6670  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CFy_Visc(
6671  iMarker_Monitoring);
6672  Surface_CFz_Visc[iMarker_Monitoring] =
6673  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CFz_Visc(
6674  iMarker_Monitoring);
6675 
6676  Surface_CL_Mnt[iMarker_Monitoring] =
6677  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CL_Mnt(
6678  iMarker_Monitoring);
6679  Surface_CD_Mnt[iMarker_Monitoring] =
6680  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CD_Mnt(
6681  iMarker_Monitoring);
6682  Surface_CSF_Mnt[iMarker_Monitoring] =
6683  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CSF_Mnt(
6684  iMarker_Monitoring);
6685  Surface_CEff_Mnt[iMarker_Monitoring] =
6686  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CEff_Mnt(
6687  iMarker_Monitoring);
6688  Surface_CMx_Mnt[iMarker_Monitoring] =
6689  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CMx_Mnt(
6690  iMarker_Monitoring);
6691  Surface_CMy_Mnt[iMarker_Monitoring] =
6692  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CMy_Mnt(
6693  iMarker_Monitoring);
6694  Surface_CMz_Mnt[iMarker_Monitoring] =
6695  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CMz_Mnt(
6696  iMarker_Monitoring);
6697  Surface_CFx_Mnt[iMarker_Monitoring] =
6698  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CFx_Mnt(
6699  iMarker_Monitoring);
6700  Surface_CFy_Mnt[iMarker_Monitoring] =
6701  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CFy_Mnt(
6702  iMarker_Monitoring);
6703  Surface_CFz_Mnt[iMarker_Monitoring] =
6704  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CFz_Mnt(
6705  iMarker_Monitoring);
6706 
6707  }
6708 
6709 
6710  /*--- Write file name with extension ---*/
6711 
6712  string filename = config[val_iZone]->GetBreakdown_FileName();
6713  strcpy (cstr, filename.data());
6714 
6715  Breakdown_file.open(cstr, ios::out);
6716 
6717  Breakdown_file << "\n" <<"-------------------------------------------------------------------------" << "\n";
6718  Breakdown_file <<"| ___ _ _ ___ |" << "\n";
6719  Breakdown_file <<"| / __| | | |_ ) Release 6.1.0 \"Falcon\" |" << "\n";
6720  Breakdown_file <<"| \\__ \\ |_| |/ / |" << "\n";
6721  Breakdown_file <<"| |___/\\___//___| Suite (Computational Fluid Dynamics Code) |" << "\n";
6722  Breakdown_file << "| |" << "\n";
6723  //Breakdown_file << "| Local date and time: " << dt << " |" << "\n";
6724  Breakdown_file <<"-------------------------------------------------------------------------" << "\n";
6725  Breakdown_file << "| The current SU2 release has been coordinated by the |" << "\n";
6726  Breakdown_file << "| SU2 International Developers Society <www.su2devsociety.org> |" << "\n";
6727  Breakdown_file << "| with selected contributions from the open-source community |" << "\n";
6728  Breakdown_file <<"-------------------------------------------------------------------------" << "\n";
6729  Breakdown_file << "| The main research teams contributing to the current release are: |" << "\n";
6730  Breakdown_file << "| - Prof. Juan J. Alonso's group at Stanford University. |" << "\n";
6731  Breakdown_file << "| - Prof. Piero Colonna's group at Delft University of Technology. |" << "\n";
6732  Breakdown_file << "| - Prof. Nicolas R. Gauger's group at Kaiserslautern U. of Technology. |" << "\n";
6733  Breakdown_file << "| - Prof. Alberto Guardone's group at Polytechnic University of Milan. |" << "\n";
6734  Breakdown_file << "| - Prof. Rafael Palacios' group at Imperial College London. |" << "\n";
6735  Breakdown_file << "| - Prof. Vincent Terrapon's group at the University of Liege. |" << "\n";
6736  Breakdown_file << "| - Prof. Edwin van der Weide's group at the University of Twente. |" << "\n";
6737  Breakdown_file << "| - Lab. of New Concepts in Aeronautics at Tech. Inst. of Aeronautics. |" << "\n";
6738  Breakdown_file <<"-------------------------------------------------------------------------" << "\n";
6739  Breakdown_file << "| Copyright 2012-2018, Francisco D. Palacios, Thomas D. Economon, |" << "\n";
6740  Breakdown_file << "| Tim Albring, and the SU2 contributors. |" << "\n";
6741  Breakdown_file << "| |" << "\n";
6742  Breakdown_file << "| SU2 is free software; you can redistribute it and/or |" << "\n";
6743  Breakdown_file << "| modify it under the terms of the GNU Lesser General Public |" << "\n";
6744  Breakdown_file << "| License as published by the Free Software Foundation; either |" << "\n";
6745  Breakdown_file << "| version 2.1 of the License, or (at your option) any later version. |" << "\n";
6746  Breakdown_file << "| |" << "\n";
6747  Breakdown_file << "| SU2 is distributed in the hope that it will be useful, |" << "\n";
6748  Breakdown_file << "| but WITHOUT ANY WARRANTY; without even the implied warranty of |" << "\n";
6749  Breakdown_file << "| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |" << "\n";
6750  Breakdown_file << "| Lesser General Public License for more details. |" << "\n";
6751  Breakdown_file << "| |" << "\n";
6752  Breakdown_file << "| You should have received a copy of the GNU Lesser General Public |" << "\n";
6753  Breakdown_file << "| License along with SU2. If not, see <http://www.gnu.org/licenses/>. |" << "\n";
6754  Breakdown_file <<"-------------------------------------------------------------------------" << "\n";
6755 
6756  Breakdown_file.precision(6);
6757 
6758  Breakdown_file << "\n" << "\n" << "Problem definition:" << "\n" << "\n";
6759 
6760  switch (Kind_Solver) {
6761  case EULER: case INC_EULER:
6762  if (compressible) Breakdown_file << "Compressible Euler equations." << "\n";
6763  if (incompressible) Breakdown_file << "Incompressible Euler equations." << "\n";
6764  break;
6765  case NAVIER_STOKES: case INC_NAVIER_STOKES:
6766  if (compressible) Breakdown_file << "Compressible Laminar Navier-Stokes' equations." << "\n";
6767  if (incompressible) Breakdown_file << "Incompressible Laminar Navier-Stokes' equations." << "\n";
6768  break;
6769  case RANS: case INC_RANS:
6770  if (compressible) Breakdown_file << "Compressible RANS equations." << "\n";
6771  if (incompressible) Breakdown_file << "Incompressible RANS equations." << "\n";
6772  Breakdown_file << "Turbulence model: ";
6773  switch (Kind_Turb_Model) {
6774  case SA: Breakdown_file << "Spalart Allmaras" << "\n"; break;
6775  case SA_NEG: Breakdown_file << "Negative Spalart Allmaras" << "\n"; break;
6776  case SA_E: Breakdown_file << "Edwards Spalart Allmaras" << "\n"; break;
6777  case SA_COMP: Breakdown_file << "Compressibility Correction Spalart Allmaras" << "\n"; break;
6778  case SA_E_COMP: Breakdown_file << "Compressibility Correction Edwards Spalart Allmaras" << "\n"; break;
6779  case SST: Breakdown_file << "Menter's SST" << "\n"; break;
6780  case SST_SUST: Breakdown_file << "Menter's SST with sustaining terms" << "\n"; break;
6781  }
6782  break;
6783  }
6784 
6785 
6786  /*--- Compressible version of console output ---*/
6787 
6788  if (compressible) {
6789 
6790 
6791  if ((compressible) && (Kind_Solver != FEM_ELASTICITY)) {
6792  Breakdown_file << "Mach number: " << config[val_iZone]->GetMach() <<"."<< "\n";
6793  Breakdown_file << "Angle of attack (AoA): " << config[val_iZone]->GetAoA() <<" deg, and angle of sideslip (AoS): " << config[val_iZone]->GetAoS() <<" deg."<< "\n";
6794  if ((Kind_Solver == NAVIER_STOKES) || (Kind_Solver == ADJ_NAVIER_STOKES) ||
6795  (Kind_Solver == RANS) || (Kind_Solver == ADJ_RANS))
6796  Breakdown_file << "Reynolds number: " << config[val_iZone]->GetReynolds() <<"."<< "\n";
6797  }
6798 
6799  if (fixed_cl) {
6800  Breakdown_file << "Simulation at a cte. CL: " << config[val_iZone]->GetTarget_CL() << ".\n";
6801  Breakdown_file << "Approx. Delta CL / Delta AoA: " << config[val_iZone]->GetdCL_dAlpha() << " (1/deg).\n";
6802  Breakdown_file << "Approx. Delta CD / Delta CL: " << config[val_iZone]->GetdCD_dCL() << ".\n";
6803  if (nDim == 3 ) {
6804  Breakdown_file << "Approx. Delta CMx / Delta CL: " << config[val_iZone]->GetdCMx_dCL() << ".\n";
6805  Breakdown_file << "Approx. Delta CMy / Delta CL: " << config[val_iZone]->GetdCMy_dCL() << ".\n";
6806  }
6807  Breakdown_file << "Approx. Delta CMz / Delta CL: " << config[val_iZone]->GetdCMz_dCL() << ".\n";
6808  }
6809 
6810  if (Ref_NonDim == DIMENSIONAL) { Breakdown_file << "Dimensional simulation." << "\n"; }
6811  else if (Ref_NonDim == FREESTREAM_PRESS_EQ_ONE) { Breakdown_file << "Non-Dimensional simulation (P=1.0, Rho=1.0, T=1.0 at the farfield)." << "\n"; }
6812  else if (Ref_NonDim == FREESTREAM_VEL_EQ_MACH) { Breakdown_file << "Non-Dimensional simulation (V=Mach, Rho=1.0, T=1.0 at the farfield)." << "\n"; }
6813  else if (Ref_NonDim == FREESTREAM_VEL_EQ_ONE) { Breakdown_file << "Non-Dimensional simulation (V=1.0, Rho=1.0, T=1.0 at the farfield)." << "\n"; }
6814 
6815  if (config[val_iZone]->GetSystemMeasurements() == SI) {
6816  Breakdown_file << "The reference area is " << config[val_iZone]->GetRefArea() << " m^2." << "\n";
6817  Breakdown_file << "The reference length is " << config[val_iZone]->GetRefLength() << " m." << "\n";
6818  }
6819 
6820  if (config[val_iZone]->GetSystemMeasurements() == US) {
6821  Breakdown_file << "The reference area is " << config[val_iZone]->GetRefArea()*12.0*12.0 << " in^2." << "\n";
6822  Breakdown_file << "The reference length is " << config[val_iZone]->GetRefLength()*12.0 << " in." << "\n";
6823  }
6824  Breakdown_file << "\n" << "\n" <<"Problem definition:" << "\n" << "\n";
6825  if (compressible) {
6826  if (viscous) {
6827  Breakdown_file << "Viscous flow: Computing pressure using the ideal gas law" << "\n";
6828  Breakdown_file << "based on the free-stream temperature and a density computed" << "\n";
6829  Breakdown_file << "from the Reynolds number." << "\n";
6830  } else {
6831  Breakdown_file << "Inviscid flow: Computing density based on free-stream" << "\n";
6832  Breakdown_file << "temperature and pressure using the ideal gas law." << "\n";
6833  }
6834  }
6835 
6836  if (dynamic_grid) Breakdown_file << "Force coefficients computed using MACH_MOTION." << "\n";
6837  else Breakdown_file << "Force coefficients computed using free-stream values." << "\n";
6838 
6839  if (incompressible) {
6840  Breakdown_file << "Viscous and Inviscid flow: rho_ref, and vel_ref" << "\n";
6841  Breakdown_file << "are based on the free-stream values, p_ref = rho_ref*vel_ref^2." << "\n";
6842  Breakdown_file << "The free-stream value of the pressure is 0." << "\n";
6843  Breakdown_file << "Mach number: "<< config[val_iZone]->GetMach() << ", computed using the Bulk modulus." << "\n";
6844  Breakdown_file << "Angle of attack (deg): "<< config[val_iZone]->GetAoA() << ", computed using the the free-stream velocity." << "\n";
6845  Breakdown_file << "Side slip angle (deg): "<< config[val_iZone]->GetAoS() << ", computed using the the free-stream velocity." << "\n";
6846  if (viscous) Breakdown_file << "Reynolds number: " << config[val_iZone]->GetReynolds() << ", computed using free-stream values."<< "\n";
6847  Breakdown_file << "Only dimensional computation, the grid should be dimensional." << "\n";
6848  }
6849 
6850  Breakdown_file <<"-- Input conditions:"<< "\n";
6851 
6852  if (compressible) {
6853  switch (config[val_iZone]->GetKind_FluidModel()) {
6854 
6855  case STANDARD_AIR:
6856  Breakdown_file << "Fluid Model: STANDARD_AIR "<< "\n";
6857  Breakdown_file << "Specific gas constant: " << config[val_iZone]->GetGas_Constant();
6858  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " N.m/kg.K." << "\n";
6859  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " lbf.ft/slug.R." << "\n";
6860  Breakdown_file << "Specific gas constant (non-dim): " << config[val_iZone]->GetGas_ConstantND()<< "\n";
6861  Breakdown_file << "Specific Heat Ratio: 1.4000 "<< "\n";
6862  break;
6863 
6864  case IDEAL_GAS:
6865  Breakdown_file << "Fluid Model: IDEAL_GAS "<< "\n";
6866  Breakdown_file << "Specific gas constant: " << config[val_iZone]->GetGas_Constant() << " N.m/kg.K." << "\n";
6867  Breakdown_file << "Specific gas constant (non-dim): " << config[val_iZone]->GetGas_ConstantND()<< "\n";
6868  Breakdown_file << "Specific Heat Ratio: "<< config[val_iZone]->GetGamma() << "\n";
6869  break;
6870 
6871  case VW_GAS:
6872  Breakdown_file << "Fluid Model: Van der Waals "<< "\n";
6873  Breakdown_file << "Specific gas constant: " << config[val_iZone]->GetGas_Constant() << " N.m/kg.K." << "\n";
6874  Breakdown_file << "Specific gas constant (non-dim): " << config[val_iZone]->GetGas_ConstantND()<< "\n";
6875  Breakdown_file << "Specific Heat Ratio: "<< config[val_iZone]->GetGamma() << "\n";
6876  Breakdown_file << "Critical Pressure: " << config[val_iZone]->GetPressure_Critical() << " Pa." << "\n";
6877  Breakdown_file << "Critical Temperature: " << config[val_iZone]->GetTemperature_Critical() << " K." << "\n";
6878  Breakdown_file << "Critical Pressure (non-dim): " << config[val_iZone]->GetPressure_Critical() /config[val_iZone]->GetPressure_Ref() << "\n";
6879  Breakdown_file << "Critical Temperature (non-dim) : " << config[val_iZone]->GetTemperature_Critical() /config[val_iZone]->GetTemperature_Ref() << "\n";
6880  break;
6881 
6882  case PR_GAS:
6883  Breakdown_file << "Fluid Model: Peng-Robinson "<< "\n";
6884  Breakdown_file << "Specific gas constant: " << config[val_iZone]->GetGas_Constant() << " N.m/kg.K." << "\n";
6885  Breakdown_file << "Specific gas constant(non-dim): " << config[val_iZone]->GetGas_ConstantND()<< "\n";
6886  Breakdown_file << "Specific Heat Ratio: "<< config[val_iZone]->GetGamma() << "\n";
6887  Breakdown_file << "Critical Pressure: " << config[val_iZone]->GetPressure_Critical() << " Pa." << "\n";
6888  Breakdown_file << "Critical Temperature: " << config[val_iZone]->GetTemperature_Critical() << " K." << "\n";
6889  Breakdown_file << "Critical Pressure (non-dim): " << config[val_iZone]->GetPressure_Critical() /config[val_iZone]->GetPressure_Ref() << "\n";
6890  Breakdown_file << "Critical Temperature (non-dim) : " << config[val_iZone]->GetTemperature_Critical() /config[val_iZone]->GetTemperature_Ref() << "\n";
6891  break;
6892  }
6893 
6894  if (viscous) {
6895 
6896  switch (config[val_iZone]->GetKind_ViscosityModel()) {
6897 
6898  case CONSTANT_VISCOSITY:
6899  Breakdown_file << "Viscosity Model: CONSTANT_VISCOSITY "<< "\n";
6900  Breakdown_file << "Laminar Viscosity: " << config[val_iZone]->GetMu_Constant();
6901  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " N.s/m^2." << "\n";
6902  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " lbf.s/ft^2." << "\n";
6903  Breakdown_file << "Laminar Viscosity (non-dim): " << config[val_iZone]->GetMu_ConstantND()<< "\n";
6904  break;
6905 
6906  case SUTHERLAND:
6907  Breakdown_file << "Viscosity Model: SUTHERLAND "<< "\n";
6908  Breakdown_file << "Ref. Laminar Viscosity: " << config[val_iZone]->GetMu_Ref();
6909  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " N.s/m^2." << "\n";
6910  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " lbf.s/ft^2." << "\n";
6911  Breakdown_file << "Ref. Temperature: " << config[val_iZone]->GetMu_Temperature_Ref();
6912  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " K." << "\n";
6913  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " R." << "\n";
6914  Breakdown_file << "Sutherland Constant: "<< config[val_iZone]->GetMu_S();
6915  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " K." << "\n";
6916  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " R." << "\n";
6917  Breakdown_file << "Laminar Viscosity (non-dim): " << config[val_iZone]->GetMu_ConstantND()<< "\n";
6918  Breakdown_file << "Ref. Temperature (non-dim): " << config[val_iZone]->GetMu_Temperature_RefND()<< "\n";
6919  Breakdown_file << "Sutherland constant (non-dim): "<< config[val_iZone]->GetMu_SND()<< "\n";
6920  break;
6921 
6922  }
6923  switch (config[val_iZone]->GetKind_ConductivityModel()) {
6924 
6925  case CONSTANT_PRANDTL:
6926  Breakdown_file << "Conductivity Model: CONSTANT_PRANDTL "<< "\n";
6927  Breakdown_file << "Prandtl: " << config[val_iZone]->GetPrandtl_Lam()<< "\n";
6928  break;
6929 
6930  case CONSTANT_CONDUCTIVITY:
6931  Breakdown_file << "Conductivity Model: CONSTANT_CONDUCTIVITY "<< "\n";
6932  Breakdown_file << "Molecular Conductivity: " << config[val_iZone]->GetKt_Constant()<< " W/m^2.K." << "\n";
6933  Breakdown_file << "Molecular Conductivity (non-dim): " << config[val_iZone]->GetKt_ConstantND()<< "\n";
6934  break;
6935 
6936  }
6937 
6938  if ((Kind_Solver == RANS) || (Kind_Solver == ADJ_RANS) || (Kind_Solver == DISC_ADJ_RANS)) {
6939  switch (config[val_iZone]->GetKind_ConductivityModel_Turb()) {
6940  case CONSTANT_PRANDTL_TURB:
6941  Breakdown_file << "Turbulent Conductivity Model: CONSTANT_PRANDTL_TURB "<< "\n";
6942  Breakdown_file << "Turbulent Prandtl: " << config[val_iZone]->GetPrandtl_Turb()<< "\n";
6943  break;
6944  case NO_CONDUCTIVITY_TURB:
6945  Breakdown_file << "Turbulent Conductivity Model: NO_CONDUCTIVITY_TURB "<< "\n";
6946  Breakdown_file << "No turbulent component in effective thermal conductivity." << "\n";
6947  break;
6948  }
6949  }
6950 
6951  }
6952  }
6953 
6954  if (incompressible) {
6955  Breakdown_file << "Bulk modulus: " << config[val_iZone]->GetBulk_Modulus();
6956  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " Pa." << "\n";
6957  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " psf." << "\n";
6958  Breakdown_file << "Epsilon^2 multiplier of Beta for incompressible preconditioner: " << config[val_iZone]->GetBeta_Factor();
6959  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " Pa." << "\n";
6960  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " psf." << "\n";
6961  }
6962 
6963  Breakdown_file << "Free-stream static pressure: " << config[val_iZone]->GetPressure_FreeStream();
6964  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " Pa." << "\n";
6965  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " psf." << "\n";
6966 
6967  Breakdown_file << "Free-stream total pressure: " << config[val_iZone]->GetPressure_FreeStream() * pow( 1.0+config[val_iZone]->GetMach()*config[val_iZone]->GetMach()*0.5*(config[val_iZone]->GetGamma()-1.0), config[val_iZone]->GetGamma()/(config[val_iZone]->GetGamma()-1.0) );
6968  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " Pa." << "\n";
6969  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " psf." << "\n";
6970 
6971  if (compressible) {
6972  Breakdown_file << "Free-stream temperature: " << config[val_iZone]->GetTemperature_FreeStream();
6973  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " K." << "\n";
6974  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " R." << "\n";
6975 
6976  Breakdown_file << "Free-stream total temperature: " << config[val_iZone]->GetTemperature_FreeStream() * (1.0 + config[val_iZone]->GetMach() * config[val_iZone]->GetMach() * 0.5 * (config[val_iZone]->GetGamma() - 1.0));
6977  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " K." << "\n";
6978  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " R." << "\n";
6979  }
6980 
6981  Breakdown_file << "Free-stream density: " << config[val_iZone]->GetDensity_FreeStream();
6982  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " kg/m^3." << "\n";
6983  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " slug/ft^3." << "\n";
6984 
6985  if (nDim == 2) {
6986  Breakdown_file << "Free-stream velocity: (" << config[val_iZone]->GetVelocity_FreeStream()[0] << ", ";
6987  Breakdown_file << config[val_iZone]->GetVelocity_FreeStream()[1] << ")";
6988  }
6989  if (nDim == 3) {
6990  Breakdown_file << "Free-stream velocity: (" << config[val_iZone]->GetVelocity_FreeStream()[0] << ", ";
6991  Breakdown_file << config[val_iZone]->GetVelocity_FreeStream()[1] << ", " << config[val_iZone]->GetVelocity_FreeStream()[2] << ")";
6992  }
6993  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " m/s. ";
6994  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " ft/s. ";
6995 
6996  Breakdown_file << "Magnitude: " << config[val_iZone]->GetModVel_FreeStream();
6997  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " m/s." << "\n";
6998  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " ft/s." << "\n";
6999 
7000  if (compressible) {
7001  Breakdown_file << "Free-stream total energy per unit mass: " << config[val_iZone]->GetEnergy_FreeStream();
7002  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " m^2/s^2." << "\n";
7003  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " ft^2/s^2." << "\n";
7004  }
7005 
7006  if (viscous) {
7007  Breakdown_file << "Free-stream viscosity: " << config[val_iZone]->GetViscosity_FreeStream();
7008  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " N.s/m^2." << "\n";
7009  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " lbf.s/ft^2." << "\n";
7010  if (turbulent) {
7011  Breakdown_file << "Free-stream turb. kinetic energy per unit mass: " << config[val_iZone]->GetTke_FreeStream();
7012  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " m^2/s^2." << "\n";
7013  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " ft^2/s^2." << "\n";
7014  Breakdown_file << "Free-stream specific dissipation: " << config[val_iZone]->GetOmega_FreeStream();
7015  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " 1/s." << "\n";
7016  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " 1/s." << "\n";
7017  }
7018  }
7019 
7020  if (unsteady) { Breakdown_file << "Total time: " << config[val_iZone]->GetTotal_UnstTime() << " s. Time step: " << config[val_iZone]->GetDelta_UnstTime() << " s." << "\n"; }
7021 
7022  /*--- Print out reference values. ---*/
7023 
7024  Breakdown_file <<"-- Reference values:"<< "\n";
7025 
7026  if (compressible) {
7027  Breakdown_file << "Reference specific gas constant: " << config[val_iZone]->GetGas_Constant_Ref();
7028  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " N.m/kg.K." << "\n";
7029  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " lbf.ft/slug.R." << "\n";
7030  }
7031 
7032  Breakdown_file << "Reference pressure: " << config[val_iZone]->GetPressure_Ref();
7033  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " Pa." << "\n";
7034  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " psf." << "\n";
7035 
7036  if (compressible) {
7037  Breakdown_file << "Reference temperature: " << config[val_iZone]->GetTemperature_Ref();
7038  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " K." << "\n";
7039  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " R." << "\n";
7040  }
7041 
7042  Breakdown_file << "Reference density: " << config[val_iZone]->GetDensity_Ref();
7043  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " kg/m^3." << "\n";
7044  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " slug/ft^3." << "\n";
7045 
7046  Breakdown_file << "Reference velocity: " << config[val_iZone]->GetVelocity_Ref();
7047  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " m/s." << "\n";
7048  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " ft/s." << "\n";
7049 
7050  if (compressible) {
7051  Breakdown_file << "Reference energy per unit mass: " << config[val_iZone]->GetEnergy_Ref();
7052  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " m^2/s^2." << "\n";
7053  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " ft^2/s^2." << "\n";
7054  }
7055 
7056  if (incompressible) {
7057  Breakdown_file << "Reference length: " << config[val_iZone]->GetLength_Ref();
7058  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " m." << "\n";
7059  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " in." << "\n";
7060  }
7061 
7062  if (viscous) {
7063  Breakdown_file << "Reference viscosity: " << config[val_iZone]->GetViscosity_Ref();
7064  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " N.s/m^2." << "\n";
7065  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " lbf.s/ft^2." << "\n";
7066  if (compressible){
7067  Breakdown_file << "Reference conductivity: " << config[val_iZone]->GetConductivity_Ref();
7068  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " W/m^2.K." << "\n";
7069  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " lbf/ft.s.R." << "\n";
7070  }
7071  }
7072 
7073 
7074  if (unsteady) Breakdown_file << "Reference time: " << config[val_iZone]->GetTime_Ref() <<" s." << "\n";
7075 
7076  /*--- Print out resulting non-dim values here. ---*/
7077 
7078  Breakdown_file << "-- Resulting non-dimensional state:" << "\n";
7079  Breakdown_file << "Mach number (non-dim): " << config[val_iZone]->GetMach() << "\n";
7080  if (viscous) {
7081  Breakdown_file << "Reynolds number (non-dim): " << config[val_iZone]->GetReynolds() <<". Re length: " << config[val_iZone]->GetLength_Reynolds();
7082  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " m." << "\n";
7083  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " ft." << "\n";
7084  }
7085  if (gravity) {
7086  Breakdown_file << "Froude number (non-dim): " << config[val_iZone]->GetFroude() << "\n";
7087  Breakdown_file << "Lenght of the baseline wave (non-dim): " << 2.0*PI_NUMBER*config[val_iZone]->GetFroude()*config[val_iZone]->GetFroude() << "\n";
7088  }
7089 
7090  if (compressible) {
7091  Breakdown_file << "Specific gas constant (non-dim): " << config[val_iZone]->GetGas_ConstantND() << "\n";
7092  Breakdown_file << "Free-stream temperature (non-dim): " << config[val_iZone]->GetTemperature_FreeStreamND() << "\n";
7093  }
7094 
7095  Breakdown_file << "Free-stream pressure (non-dim): " << config[val_iZone]->GetPressure_FreeStreamND() << "\n";
7096 
7097  Breakdown_file << "Free-stream density (non-dim): " << config[val_iZone]->GetDensity_FreeStreamND() << "\n";
7098 
7099  if (nDim == 2) {
7100  Breakdown_file << "Free-stream velocity (non-dim): (" << config[val_iZone]->GetVelocity_FreeStreamND()[0] << ", ";
7101  Breakdown_file << config[val_iZone]->GetVelocity_FreeStreamND()[1] << "). ";
7102  } else {
7103  Breakdown_file << "Free-stream velocity (non-dim): (" << config[val_iZone]->GetVelocity_FreeStreamND()[0] << ", ";
7104  Breakdown_file << config[val_iZone]->GetVelocity_FreeStreamND()[1] << ", " << config[val_iZone]->GetVelocity_FreeStreamND()[2] << "). ";
7105  }
7106  Breakdown_file << "Magnitude: " << config[val_iZone]->GetModVel_FreeStreamND() << "\n";
7107 
7108  if (compressible)
7109  Breakdown_file << "Free-stream total energy per unit mass (non-dim): " << config[val_iZone]->GetEnergy_FreeStreamND() << "\n";
7110 
7111  if (viscous) {
7112  Breakdown_file << "Free-stream viscosity (non-dim): " << config[val_iZone]->GetViscosity_FreeStreamND() << "\n";
7113  if (turbulent) {
7114  Breakdown_file << "Free-stream turb. kinetic energy (non-dim): " << config[val_iZone]->GetTke_FreeStreamND() << "\n";
7115  Breakdown_file << "Free-stream specific dissipation (non-dim): " << config[val_iZone]->GetOmega_FreeStreamND() << "\n";
7116  }
7117  }
7118 
7119  if (unsteady) {
7120  Breakdown_file << "Total time (non-dim): " << config[val_iZone]->GetTotal_UnstTimeND() << "\n";
7121  Breakdown_file << "Time step (non-dim): " << config[val_iZone]->GetDelta_UnstTimeND() << "\n";
7122  }
7123 
7124  } else {
7125 
7126  /*--- Incompressible version of the console output ---*/
7127 
7128  bool energy = config[val_iZone]->GetEnergy_Equation();
7129  bool boussinesq = (config[val_iZone]->GetKind_DensityModel() == BOUSSINESQ);
7130 
7131  if (config[val_iZone]->GetRef_Inc_NonDim() == DIMENSIONAL) {
7132  Breakdown_file << "Viscous and Inviscid flow: rho_ref, vel_ref, temp_ref, p_ref" << "\n";
7133  Breakdown_file << "are set to 1.0 in order to perform a dimensional calculation." << "\n";
7134  if (dynamic_grid) Breakdown_file << "Force coefficients computed using MACH_MOTION." << "\n";
7135  else Breakdown_file << "Force coefficients computed using initial values." << "\n";
7136  }
7137  else if (config[val_iZone]->GetRef_Inc_NonDim() == INITIAL_VALUES) {
7138  Breakdown_file << "Viscous and Inviscid flow: rho_ref, vel_ref, and temp_ref" << "\n";
7139  Breakdown_file << "are based on the initial values, p_ref = rho_ref*vel_ref^2." << "\n";
7140  if (dynamic_grid) Breakdown_file << "Force coefficients computed using MACH_MOTION." << "\n";
7141  else Breakdown_file << "Force coefficients computed using initial values." << "\n";
7142  }
7143  else if (config[val_iZone]->GetRef_Inc_NonDim() == REFERENCE_VALUES) {
7144  Breakdown_file << "Viscous and Inviscid flow: rho_ref, vel_ref, and temp_ref" << "\n";
7145  Breakdown_file << "are user-provided reference values, p_ref = rho_ref*vel_ref^2." << "\n";
7146  if (dynamic_grid) Breakdown_file << "Force coefficients computed using MACH_MOTION." << "\n";
7147  else Breakdown_file << "Force coefficients computed using reference values." << "\n";
7148  }
7149  Breakdown_file << "The reference area for force coeffs. is " << config[val_iZone]->GetRefArea() << " m^2." << "\n";
7150  Breakdown_file << "The reference length for force coeffs. is " << config[val_iZone]->GetRefLength() << " m." << "\n";
7151 
7152  Breakdown_file << "The pressure is decomposed into thermodynamic and dynamic components." << "\n";
7153  Breakdown_file << "The initial value of the dynamic pressure is 0." << "\n";
7154 
7155  Breakdown_file << "Mach number: "<< config[val_iZone]->GetMach();
7156  if (config[val_iZone]->GetKind_FluidModel() == CONSTANT_DENSITY) {
7157  Breakdown_file << ", computed using the Bulk modulus." << "\n";
7158  } else {
7159  Breakdown_file << ", computed using fluid speed of sound." << "\n";
7160  }
7161 
7162  Breakdown_file << "For external flows, the initial state is imposed at the far-field." << "\n";
7163  Breakdown_file << "Angle of attack (deg): "<< config[val_iZone]->GetAoA() << ", computed using the initial velocity." << "\n";
7164  Breakdown_file << "Side slip angle (deg): "<< config[val_iZone]->GetAoS() << ", computed using the initial velocity." << "\n";
7165 
7166  if (viscous) {
7167  Breakdown_file << "Reynolds number per meter: " << config[val_iZone]->GetReynolds() << ", computed using initial values."<< "\n";
7168  Breakdown_file << "Reynolds number is a byproduct of inputs only (not used internally)." << "\n";
7169  }
7170  Breakdown_file << "SI units only. The grid should be dimensional (meters)." << "\n";
7171 
7172  switch (config[val_iZone]->GetKind_DensityModel()) {
7173 
7174  case CONSTANT:
7175  if (energy) Breakdown_file << "Energy equation is active and decoupled." << "\n";
7176  else Breakdown_file << "No energy equation." << "\n";
7177  break;
7178 
7179  case BOUSSINESQ:
7180  if (energy) Breakdown_file << "Energy equation is active and coupled through Boussinesq approx." << "\n";
7181  break;
7182 
7183  case VARIABLE:
7184  if (energy) Breakdown_file << "Energy equation is active and coupled for variable density." << "\n";
7185  break;
7186 
7187  }
7188 
7189  Breakdown_file <<"-- Input conditions:"<< "\n";
7190 
7191  switch (config[val_iZone]->GetKind_FluidModel()) {
7192 
7193  case CONSTANT_DENSITY:
7194  Breakdown_file << "Fluid Model: CONSTANT_DENSITY "<< "\n";
7195  if (energy) {
7196  Breakdown_file << "Specific heat at constant pressure (Cp): " << config[val_iZone]->GetSpecific_Heat_Cp() << " N.m/kg.K." << "\n";
7197  }
7198  if (boussinesq) Breakdown_file << "Thermal expansion coefficient: " << config[val_iZone]->GetThermal_Expansion_Coeff() << " K^-1." << "\n";
7199  Breakdown_file << "Thermodynamic pressure not required." << "\n";
7200  break;
7201 
7202  case INC_IDEAL_GAS:
7203  Breakdown_file << "Fluid Model: INC_IDEAL_GAS "<< endl;
7204  Breakdown_file << "Variable density incompressible flow using ideal gas law." << endl;
7205  Breakdown_file << "Density is a function of temperature (constant thermodynamic pressure)." << endl;
7206  Breakdown_file << "Specific heat at constant pressure (Cp): " << config[val_iZone]->GetSpecific_Heat_Cp() << " N.m/kg.K." << endl;
7207  Breakdown_file << "Molecular weight : "<< config[val_iZone]->GetMolecular_Weight() << " g/mol" << endl;
7208  Breakdown_file << "Specific gas constant: " << config[val_iZone]->GetGas_Constant() << " N.m/kg.K." << endl;
7209  Breakdown_file << "Thermodynamic pressure: " << config[val_iZone]->GetPressure_Thermodynamic();
7210  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " Pa." << endl;
7211  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " psf." << endl;
7212  break;
7213 
7214  case INC_IDEAL_GAS_POLY:
7215  Breakdown_file << "Fluid Model: INC_IDEAL_GAS_POLY "<< endl;
7216  Breakdown_file << "Variable density incompressible flow using ideal gas law." << endl;
7217  Breakdown_file << "Density is a function of temperature (constant thermodynamic pressure)." << endl;
7218  Breakdown_file << "Molecular weight: " << config[val_iZone]->GetMolecular_Weight() << " g/mol." << endl;
7219  Breakdown_file << "Specific gas constant: " << config[val_iZone]->GetGas_Constant() << " N.m/kg.K." << endl;
7220  Breakdown_file << "Specific gas constant (non-dim): " << config[val_iZone]->GetGas_ConstantND() << endl;
7221  Breakdown_file << "Thermodynamic pressure: " << config[val_iZone]->GetPressure_Thermodynamic();
7222  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " Pa." << endl;
7223  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " psf." << endl;
7224  Breakdown_file << "Cp(T) polynomial coefficients: \n (";
7225  for (unsigned short iVar = 0; iVar < config[val_iZone]->GetnPolyCoeffs(); iVar++) {
7226  Breakdown_file << config[val_iZone]->GetCp_PolyCoeff(iVar);
7227  if (iVar < config[val_iZone]->GetnPolyCoeffs()-1) Breakdown_file << ", ";
7228  }
7229  Breakdown_file << ")." << endl;
7230  Breakdown_file << "Cp(T) polynomial coefficients (non-dim.): \n (";
7231  for (unsigned short iVar = 0; iVar < config[val_iZone]->GetnPolyCoeffs(); iVar++) {
7232  Breakdown_file << config[val_iZone]->GetCp_PolyCoeffND(iVar);
7233  if (iVar < config[val_iZone]->GetnPolyCoeffs()-1) Breakdown_file << ", ";
7234  }
7235  Breakdown_file << ")." << endl;
7236  break;
7237 
7238  }
7239  if (viscous) {
7240  switch (config[val_iZone]->GetKind_ViscosityModel()) {
7241 
7242  case CONSTANT_VISCOSITY:
7243  Breakdown_file << "Viscosity Model: CONSTANT_VISCOSITY "<< "\n";
7244  Breakdown_file << "Constant Laminar Viscosity: " << config[val_iZone]->GetMu_Constant();
7245  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " N.s/m^2." << "\n";
7246  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " lbf.s/ft^2." << "\n";
7247  Breakdown_file << "Laminar Viscosity (non-dim): " << config[val_iZone]->GetMu_ConstantND()<< "\n";
7248  break;
7249 
7250  case SUTHERLAND:
7251  Breakdown_file << "Viscosity Model: SUTHERLAND "<< "\n";
7252  Breakdown_file << "Ref. Laminar Viscosity: " << config[val_iZone]->GetMu_Ref();
7253  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " N.s/m^2." << "\n";
7254  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " lbf.s/ft^2." << "\n";
7255  Breakdown_file << "Ref. Temperature: " << config[val_iZone]->GetMu_Temperature_Ref();
7256  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " K." << "\n";
7257  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " R." << "\n";
7258  Breakdown_file << "Sutherland Constant: "<< config[val_iZone]->GetMu_S();
7259  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " K." << "\n";
7260  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " R." << "\n";
7261  Breakdown_file << "Laminar Viscosity (non-dim): " << config[val_iZone]->GetMu_ConstantND()<< "\n";
7262  Breakdown_file << "Ref. Temperature (non-dim): " << config[val_iZone]->GetMu_Temperature_RefND()<< "\n";
7263  Breakdown_file << "Sutherland constant (non-dim): "<< config[val_iZone]->GetMu_SND()<< "\n";
7264  break;
7265 
7266  case POLYNOMIAL_VISCOSITY:
7267  Breakdown_file << "Viscosity Model: POLYNOMIAL_VISCOSITY "<< endl;
7268  Breakdown_file << "Mu(T) polynomial coefficients: \n (";
7269  for (unsigned short iVar = 0; iVar < config[val_iZone]->GetnPolyCoeffs(); iVar++) {
7270  Breakdown_file << config[val_iZone]->GetMu_PolyCoeff(iVar);
7271  if (iVar < config[val_iZone]->GetnPolyCoeffs()-1) Breakdown_file << ", ";
7272  }
7273  Breakdown_file << ")." << endl;
7274  Breakdown_file << "Mu(T) polynomial coefficients (non-dim.): \n (";
7275  for (unsigned short iVar = 0; iVar < config[val_iZone]->GetnPolyCoeffs(); iVar++) {
7276  Breakdown_file << config[val_iZone]->GetMu_PolyCoeffND(iVar);
7277  if (iVar < config[val_iZone]->GetnPolyCoeffs()-1) Breakdown_file << ", ";
7278  }
7279  Breakdown_file << ")." << endl;
7280  break;
7281 
7282  }
7283 
7284  if (energy) {
7285  switch (config[val_iZone]->GetKind_ConductivityModel()) {
7286 
7287  case CONSTANT_PRANDTL:
7288  Breakdown_file << "Conductivity Model: CONSTANT_PRANDTL "<< "\n";
7289  Breakdown_file << "Prandtl (Laminar): " << config[val_iZone]->GetPrandtl_Lam()<< "\n";
7290  break;
7291 
7292  case CONSTANT_CONDUCTIVITY:
7293  Breakdown_file << "Conductivity Model: CONSTANT_CONDUCTIVITY "<< "\n";
7294  Breakdown_file << "Molecular Conductivity: " << config[val_iZone]->GetKt_Constant()<< " W/m^2.K." << "\n";
7295  Breakdown_file << "Molecular Conductivity (non-dim): " << config[val_iZone]->GetKt_ConstantND()<< "\n";
7296  break;
7297 
7299  Breakdown_file << "Viscosity Model: POLYNOMIAL_CONDUCTIVITY "<< endl;
7300  Breakdown_file << "Kt(T) polynomial coefficients: \n (";
7301  for (unsigned short iVar = 0; iVar < config[val_iZone]->GetnPolyCoeffs(); iVar++) {
7302  Breakdown_file << config[val_iZone]->GetKt_PolyCoeff(iVar);
7303  if (iVar < config[val_iZone]->GetnPolyCoeffs()-1) Breakdown_file << ", ";
7304  }
7305  Breakdown_file << ")." << endl;
7306  Breakdown_file << "Kt(T) polynomial coefficients (non-dim.): \n (";
7307  for (unsigned short iVar = 0; iVar < config[val_iZone]->GetnPolyCoeffs(); iVar++) {
7308  Breakdown_file << config[val_iZone]->GetKt_PolyCoeffND(iVar);
7309  if (iVar < config[val_iZone]->GetnPolyCoeffs()-1) Breakdown_file << ", ";
7310  }
7311  Breakdown_file << ")." << endl;
7312  break;
7313 
7314  }
7315 
7316  if ((Kind_Solver == RANS) || (Kind_Solver == ADJ_RANS) || (Kind_Solver == DISC_ADJ_RANS)) {
7317  switch (config[val_iZone]->GetKind_ConductivityModel_Turb()) {
7318  case CONSTANT_PRANDTL_TURB:
7319  Breakdown_file << "Turbulent Conductivity Model: CONSTANT_PRANDTL_TURB "<< "\n";
7320  Breakdown_file << "Turbulent Prandtl: " << config[val_iZone]->GetPrandtl_Turb()<< "\n";
7321  break;
7322  case NO_CONDUCTIVITY_TURB:
7323  Breakdown_file << "Turbulent Conductivity Model: NO_CONDUCTIVITY_TURB "<< "\n";
7324  Breakdown_file << "No turbulent component in effective thermal conductivity." << "\n";
7325  break;
7326  }
7327  }
7328 
7329  }
7330 
7331  }
7332 
7333  if (config[val_iZone]->GetKind_FluidModel() == CONSTANT_DENSITY) {
7334  Breakdown_file << "Bulk modulus: " << config[val_iZone]->GetBulk_Modulus();
7335  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " Pa." << "\n";
7336  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " psf." << "\n";
7337  }
7338 
7339  Breakdown_file << "Initial dynamic pressure: " << config[val_iZone]->GetPressure_FreeStream();
7340  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " Pa." << "\n";
7341  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " psf." << "\n";
7342 
7343  Breakdown_file << "Initial total pressure: " << config[val_iZone]->GetPressure_FreeStream() + 0.5*config[val_iZone]->GetDensity_FreeStream()*config[val_iZone]->GetModVel_FreeStream()*config[val_iZone]->GetModVel_FreeStream();
7344  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " Pa." << "\n";
7345  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " psf." << "\n";
7346 
7347  if (energy) {
7348  Breakdown_file << "Initial temperature: " << config[val_iZone]->GetTemperature_FreeStream();
7349  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " K." << "\n";
7350  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " R." << "\n";
7351  }
7352 
7353  Breakdown_file << "Initial density: " << config[val_iZone]->GetDensity_FreeStream();
7354  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " kg/m^3." << "\n";
7355  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " slug/ft^3." << "\n";
7356 
7357  if (nDim == 2) {
7358  Breakdown_file << "Initial velocity: (" << config[val_iZone]->GetVelocity_FreeStream()[0] << ", ";
7359  Breakdown_file << config[val_iZone]->GetVelocity_FreeStream()[1] << ")";
7360  }
7361  if (nDim == 3) {
7362  Breakdown_file << "Initial velocity: (" << config[val_iZone]->GetVelocity_FreeStream()[0] << ", ";
7363  Breakdown_file << config[val_iZone]->GetVelocity_FreeStream()[1] << ", " << config[val_iZone]->GetVelocity_FreeStream()[2] << ")";
7364  }
7365  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " m/s. ";
7366  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " ft/s. ";
7367 
7368  Breakdown_file << "Magnitude: " << config[val_iZone]->GetModVel_FreeStream();
7369  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " m/s." << "\n";
7370  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " ft/s." << "\n";
7371 
7372  if (viscous) {
7373  Breakdown_file << "Initial laminar viscosity: " << config[val_iZone]->GetViscosity_FreeStream();
7374  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " N.s/m^2." << "\n";
7375  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " lbf.s/ft^2." << "\n";
7376  if (turbulent) {
7377  Breakdown_file << "Initial turb. kinetic energy per unit mass: " << config[val_iZone]->GetTke_FreeStream();
7378  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " m^2/s^2." << "\n";
7379  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " ft^2/s^2." << "\n";
7380  Breakdown_file << "Initial specific dissipation: " << config[val_iZone]->GetOmega_FreeStream();
7381  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " 1/s." << "\n";
7382  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " 1/s." << "\n";
7383  }
7384  }
7385 
7386  if (unsteady) { Breakdown_file << "Total time: " << config[val_iZone]->GetTotal_UnstTime() << " s. Time step: " << config[val_iZone]->GetDelta_UnstTime() << " s." << "\n"; }
7387 
7388  /*--- Print out reference values. ---*/
7389 
7390  Breakdown_file <<"-- Reference values:"<< "\n";
7391 
7392  if (config[val_iZone]->GetKind_FluidModel() != CONSTANT_DENSITY) {
7393  Breakdown_file << "Reference specific gas constant: " << config[val_iZone]->GetGas_Constant_Ref();
7394  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " N.m/kg.K." << "\n";
7395  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " lbf.ft/slug.R." << "\n";
7396  } else {
7397  if (energy) {
7398  Breakdown_file << "Reference specific heat: " << config[val_iZone]->GetGas_Constant_Ref();
7399  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " N.m/kg.K." << "\n";
7400  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " lbf.ft/slug.R." << "\n";
7401  }
7402  }
7403 
7404  Breakdown_file << "Reference pressure: " << config[val_iZone]->GetPressure_Ref();
7405  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " Pa." << "\n";
7406  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " psf." << "\n";
7407 
7408  if (energy) {
7409  Breakdown_file << "Reference temperature: " << config[val_iZone]->GetTemperature_Ref();
7410  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " K." << "\n";
7411  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " R." << "\n";
7412  }
7413 
7414  Breakdown_file << "Reference density: " << config[val_iZone]->GetDensity_Ref();
7415  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " kg/m^3." << "\n";
7416  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " slug/ft^3." << "\n";
7417 
7418  Breakdown_file << "Reference velocity: " << config[val_iZone]->GetVelocity_Ref();
7419  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " m/s." << "\n";
7420  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " ft/s." << "\n";
7421 
7422  Breakdown_file << "Reference length: " << config[val_iZone]->GetLength_Ref();
7423  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " m." << "\n";
7424  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " in." << "\n";
7425 
7426  if (viscous) {
7427  Breakdown_file << "Reference viscosity: " << config[val_iZone]->GetViscosity_Ref();
7428  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " N.s/m^2." << "\n";
7429  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " lbf.s/ft^2." << "\n";
7430  }
7431 
7432  if (unsteady) Breakdown_file << "Reference time: " << config[val_iZone]->GetTime_Ref() <<" s." << "\n";
7433 
7434  /*--- Print out resulting non-dim values here. ---*/
7435 
7436  Breakdown_file << "-- Resulting non-dimensional state:" << "\n";
7437  Breakdown_file << "Mach number (non-dim): " << config[val_iZone]->GetMach() << "\n";
7438  if (viscous) {
7439  Breakdown_file << "Reynolds number (per m): " << config[val_iZone]->GetReynolds() << "\n";
7440  }
7441 
7442  if (config[val_iZone]->GetKind_FluidModel() != CONSTANT_DENSITY) {
7443  Breakdown_file << "Specific gas constant (non-dim): " << config[val_iZone]->GetGas_ConstantND() << "\n";
7444  Breakdown_file << "Initial thermodynamic pressure (non-dim): " << config[val_iZone]->GetPressure_ThermodynamicND() << "\n";
7445  } else {
7446  if (energy) {
7447  Breakdown_file << "Specific heat at constant pressure (non-dim): " << config[val_iZone]->GetSpecific_Heat_CpND() << "\n";
7448  if (boussinesq) Breakdown_file << "Thermal expansion coefficient (non-dim.): " << config[val_iZone]->GetThermal_Expansion_CoeffND() << " K^-1." << "\n";
7449  }
7450  }
7451 
7452  if (energy) Breakdown_file << "Initial temperature (non-dim): " << config[val_iZone]->GetTemperature_FreeStreamND() << "\n";
7453  Breakdown_file << "Initial pressure (non-dim): " << config[val_iZone]->GetPressure_FreeStreamND() << "\n";
7454  Breakdown_file << "Initial density (non-dim): " << config[val_iZone]->GetDensity_FreeStreamND() << "\n";
7455 
7456  if (nDim == 2) {
7457  Breakdown_file << "Initial velocity (non-dim): (" << config[val_iZone]->GetVelocity_FreeStreamND()[0] << ", ";
7458  Breakdown_file << config[val_iZone]->GetVelocity_FreeStreamND()[1] << "). ";
7459  } else {
7460  Breakdown_file << "Initial velocity (non-dim): (" << config[val_iZone]->GetVelocity_FreeStreamND()[0] << ", ";
7461  Breakdown_file << config[val_iZone]->GetVelocity_FreeStreamND()[1] << ", " << config[val_iZone]->GetVelocity_FreeStreamND()[2] << "). ";
7462  }
7463  Breakdown_file << "Magnitude: " << config[val_iZone]->GetModVel_FreeStreamND() << "\n";
7464 
7465  if (viscous) {
7466  Breakdown_file << "Initial viscosity (non-dim): " << config[val_iZone]->GetViscosity_FreeStreamND() << "\n";
7467  if (turbulent) {
7468  Breakdown_file << "Initial turb. kinetic energy (non-dim): " << config[val_iZone]->GetTke_FreeStreamND() << "\n";
7469  Breakdown_file << "Initial specific dissipation (non-dim): " << config[val_iZone]->GetOmega_FreeStreamND() << "\n";
7470  }
7471  }
7472 
7473  if (unsteady) {
7474  Breakdown_file << "Total time (non-dim): " << config[val_iZone]->GetTotal_UnstTimeND() << "\n";
7475  Breakdown_file << "Time step (non-dim): " << config[val_iZone]->GetDelta_UnstTimeND() << "\n";
7476  }
7477 
7478  }
7479 
7480  /*--- Begin forces breakdown info. ---*/
7481 
7482  Breakdown_file << fixed;
7483  Breakdown_file << "\n" << "\n" <<"Forces breakdown:" << "\n" << "\n";
7484 
7485  if (nDim == 3) {
7486  su2double m = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CFz()/solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CFx();
7487  su2double term = (Total_CoPz/m)-Total_CoPx;
7488 
7489  if (term > 0) Breakdown_file << "Center of Pressure: X=" << 1/m <<"Z-"<< term << "." << "\n\n";
7490  else Breakdown_file << "Center of Pressure: X=" << 1/m <<"Z+"<< fabs(term);
7491  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " m." << "\n\n";
7492  else Breakdown_file << " in." << "\n\n";
7493  }
7494  else {
7495  su2double m = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CFy()/solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CFx();
7496  su2double term = (Total_CoPy/m)-Total_CoPx;
7497  if (term > 0) Breakdown_file << "Center of Pressure: X=" << 1/m <<"Y-"<< term << "." << "\n\n";
7498  else Breakdown_file << "Center of Pressure: X=" << 1/m <<"Y+"<< fabs(term);
7499  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " m." << "\n\n";
7500  else Breakdown_file << " in." << "\n\n";
7501  }
7502 
7503  /*--- Reference area and force factors. ---*/
7504 
7505  su2double RefDensity, RefArea, RefVel, Factor, Ref;
7506  RefArea = config[val_iZone]->GetRefArea();
7507  if (compressible) {
7508  RefDensity = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetDensity_Inf();
7509  RefVel = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetModVelocity_Inf();
7510  } else {
7511  if ((config[val_iZone]->GetRef_Inc_NonDim() == DIMENSIONAL) ||
7512  (config[val_iZone]->GetRef_Inc_NonDim() == INITIAL_VALUES)) {
7513  RefDensity = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetDensity_Inf();
7514  RefVel = 0.0;
7515  for (iDim = 0; iDim < nDim; iDim++)
7516  RefVel += solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetVelocity_Inf(iDim)*solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetVelocity_Inf(iDim);
7517  RefVel = sqrt(RefVel);
7518  } else {
7519  RefDensity = config[val_iZone]->GetInc_Density_Ref();
7520  RefVel = config[val_iZone]->GetInc_Velocity_Ref();
7521  }
7522  }
7523  Factor = (0.5*RefDensity*RefArea*RefVel*RefVel);
7524  Ref = config[val_iZone]->GetDensity_Ref() * config[val_iZone]->GetVelocity_Ref() * config[val_iZone]->GetVelocity_Ref() * 1.0 * 1.0;
7525 
7526  Breakdown_file << "NOTE: Multiply forces by the non-dimensional factor: " << Factor << ", and the reference factor: " << Ref << "\n";
7527  Breakdown_file << "to obtain the dimensional force." << "\n" << "\n";
7528 
7529  Breakdown_file << "Total CL: ";
7530  Breakdown_file.width(11);
7531  Breakdown_file << Total_CL;
7532  Breakdown_file << " | Pressure (";
7533  Breakdown_file.width(5);
7534  Breakdown_file << SU2_TYPE::Int((Inv_CL * 100.0) / (Total_CL + EPS));
7535  Breakdown_file << "%): ";
7536  Breakdown_file.width(11);
7537  Breakdown_file << Inv_CL;
7538  Breakdown_file << " | Friction (";
7539  Breakdown_file.width(5);
7540  Breakdown_file << SU2_TYPE::Int((Visc_CL * 100.0) / (Total_CL + EPS));
7541  Breakdown_file << "%): ";
7542  Breakdown_file.width(11);
7543  Breakdown_file << Visc_CL;
7544  Breakdown_file << " | Momentum (";
7545  Breakdown_file.width(5);
7546  Breakdown_file << SU2_TYPE::Int((Mnt_CL * 100.0) / (Total_CL + EPS));
7547  Breakdown_file << "%): ";
7548  Breakdown_file.width(11);
7549  Breakdown_file << Mnt_CL << "\n";
7550 
7551  Breakdown_file << "Total CD: ";
7552  Breakdown_file.width(11);
7553  Breakdown_file << Total_CD;
7554  Breakdown_file << " | Pressure (";
7555  Breakdown_file.width(5);
7556  Breakdown_file << SU2_TYPE::Int((Inv_CD * 100.0) / (Total_CD + EPS)) << "%): ";
7557  Breakdown_file.width(11);
7558  Breakdown_file << Inv_CD;
7559  Breakdown_file << " | Friction (";
7560  Breakdown_file.width(5);
7561  Breakdown_file << SU2_TYPE::Int((Visc_CD * 100.0) / (Total_CD + EPS)) << "%): ";
7562  Breakdown_file.width(11);
7563  Breakdown_file << Visc_CD;
7564  Breakdown_file << " | Momentum (";
7565  Breakdown_file.width(5);
7566  Breakdown_file << SU2_TYPE::Int((Mnt_CD * 100.0) / (Total_CD + EPS)) << "%): ";
7567  Breakdown_file.width(11);
7568  Breakdown_file << Mnt_CD << "\n";
7569 
7570  if (nDim == 3) {
7571  Breakdown_file << "Total CSF: ";
7572  Breakdown_file.width(11);
7573  Breakdown_file << Total_CSF;
7574  Breakdown_file << " | Pressure (";
7575  Breakdown_file.width(5);
7576  Breakdown_file << SU2_TYPE::Int((Inv_CSF * 100.0) / (Total_CSF + EPS));
7577  Breakdown_file << "%): ";
7578  Breakdown_file.width(11);
7579  Breakdown_file << Inv_CSF;
7580  Breakdown_file << " | Friction (";
7581  Breakdown_file.width(5);
7582  Breakdown_file << SU2_TYPE::Int((Visc_CSF * 100.0) / (Total_CSF + EPS));
7583  Breakdown_file << "%): ";
7584  Breakdown_file.width(11);
7585  Breakdown_file << Visc_CSF;
7586  Breakdown_file << " | Momentum (";
7587  Breakdown_file.width(5);
7588  Breakdown_file << SU2_TYPE::Int((Mnt_CSF * 100.0) / (Total_CSF + EPS));
7589  Breakdown_file << "%): ";
7590  Breakdown_file.width(11);
7591  Breakdown_file << Mnt_CSF << "\n";
7592  }
7593 
7594  Breakdown_file << "Total CL/CD: ";
7595  Breakdown_file.width(11);
7596  Breakdown_file << Total_CEff;
7597  Breakdown_file << " | Pressure (";
7598  Breakdown_file.width(5);
7599  Breakdown_file << SU2_TYPE::Int((Inv_CEff * 100.0) / (Total_CEff + EPS));
7600  Breakdown_file << "%): ";
7601  Breakdown_file.width(11);
7602  Breakdown_file << Inv_CEff;
7603  Breakdown_file << " | Friction (";
7604  Breakdown_file.width(5);
7605  Breakdown_file << SU2_TYPE::Int((Visc_CEff * 100.0) / (Total_CEff + EPS));
7606  Breakdown_file << "%): ";
7607  Breakdown_file.width(11);
7608  Breakdown_file << Visc_CEff;
7609  Breakdown_file << " | Momentum (";
7610  Breakdown_file.width(5);
7611  Breakdown_file << SU2_TYPE::Int((Mnt_CEff * 100.0) / (Total_CEff + EPS));
7612  Breakdown_file << "%): ";
7613  Breakdown_file.width(11);
7614  Breakdown_file << Mnt_CEff << "\n";
7615 
7616  if (nDim == 3) {
7617  Breakdown_file << "Total CMx: ";
7618  Breakdown_file.width(11);
7619  Breakdown_file << Total_CMx;
7620  Breakdown_file << " | Pressure (";
7621  Breakdown_file.width(5);
7622  Breakdown_file << SU2_TYPE::Int((Inv_CMx * 100.0) / (Total_CMx + EPS));
7623  Breakdown_file << "%): ";
7624  Breakdown_file.width(11);
7625  Breakdown_file << Inv_CMx;
7626  Breakdown_file << " | Friction (";
7627  Breakdown_file.width(5);
7628  Breakdown_file << SU2_TYPE::Int((Visc_CMx * 100.0) / (Total_CMx + EPS));
7629  Breakdown_file << "%): ";
7630  Breakdown_file.width(11);
7631  Breakdown_file << Visc_CMx;
7632  Breakdown_file << " | Momentum (";
7633  Breakdown_file.width(5);
7634  Breakdown_file << SU2_TYPE::Int((Mnt_CMx * 100.0) / (Total_CMx + EPS));
7635  Breakdown_file << "%): ";
7636  Breakdown_file.width(11);
7637  Breakdown_file << Mnt_CMx << "\n";
7638 
7639  Breakdown_file << "Total CMy: ";
7640  Breakdown_file.width(11);
7641  Breakdown_file << Total_CMy;
7642  Breakdown_file << " | Pressure (";
7643  Breakdown_file.width(5);
7644  Breakdown_file << SU2_TYPE::Int((Inv_CMy * 100.0) / (Total_CMy + EPS));
7645  Breakdown_file << "%): ";
7646  Breakdown_file.width(11);
7647  Breakdown_file << Inv_CMy;
7648  Breakdown_file << " | Friction (";
7649  Breakdown_file.width(5);
7650  Breakdown_file << SU2_TYPE::Int((Visc_CMy * 100.0) / (Total_CMy + EPS));
7651  Breakdown_file << "%): ";
7652  Breakdown_file.width(11);
7653  Breakdown_file << Visc_CMy;
7654  Breakdown_file << " | Momentum (";
7655  Breakdown_file.width(5);
7656  Breakdown_file << SU2_TYPE::Int((Mnt_CMz * 100.0) / (Total_CMz + EPS));
7657  Breakdown_file << "%): ";
7658  Breakdown_file.width(11);
7659  Breakdown_file << Mnt_CMy << "\n";
7660  }
7661 
7662  Breakdown_file << "Total CMz: ";
7663  Breakdown_file.width(11);
7664  Breakdown_file << Total_CMz;
7665  Breakdown_file << " | Pressure (";
7666  Breakdown_file.width(5);
7667  Breakdown_file << SU2_TYPE::Int((Inv_CMz * 100.0) / (Total_CMz + EPS));
7668  Breakdown_file << "%): ";
7669  Breakdown_file.width(11);
7670  Breakdown_file << Inv_CMz;
7671  Breakdown_file << " | Friction (";
7672  Breakdown_file.width(5);
7673  Breakdown_file << SU2_TYPE::Int((Visc_CMz * 100.0) / (Total_CMz + EPS));
7674  Breakdown_file << "%): ";
7675  Breakdown_file.width(11);
7676  Breakdown_file << Visc_CMz;
7677  Breakdown_file << " | Momentum (";
7678  Breakdown_file.width(5);
7679  Breakdown_file << SU2_TYPE::Int((Mnt_CMz * 100.0) / (Total_CMz + EPS));
7680  Breakdown_file << "%): ";
7681  Breakdown_file.width(11);
7682  Breakdown_file << Mnt_CMz << "\n";
7683 
7684  Breakdown_file << "Total CFx: ";
7685  Breakdown_file.width(11);
7686  Breakdown_file << Total_CFx;
7687  Breakdown_file << " | Pressure (";
7688  Breakdown_file.width(5);
7689  Breakdown_file << SU2_TYPE::Int((Inv_CFx * 100.0) / (Total_CFx + EPS));
7690  Breakdown_file << "%): ";
7691  Breakdown_file.width(11);
7692  Breakdown_file << Inv_CFx;
7693  Breakdown_file << " | Friction (";
7694  Breakdown_file.width(5);
7695  Breakdown_file << SU2_TYPE::Int((Visc_CFx * 100.0) / (Total_CFx + EPS));
7696  Breakdown_file << "%): ";
7697  Breakdown_file.width(11);
7698  Breakdown_file << Visc_CFx;
7699  Breakdown_file << " | Momentum (";
7700  Breakdown_file.width(5);
7701  Breakdown_file << SU2_TYPE::Int((Mnt_CFx * 100.0) / (Total_CFx + EPS));
7702  Breakdown_file << "%): ";
7703  Breakdown_file.width(11);
7704  Breakdown_file << Mnt_CFx << "\n";
7705 
7706  Breakdown_file << "Total CFy: ";
7707  Breakdown_file.width(11);
7708  Breakdown_file << Total_CFy;
7709  Breakdown_file << " | Pressure (";
7710  Breakdown_file.width(5);
7711  Breakdown_file << SU2_TYPE::Int((Inv_CFy * 100.0) / (Total_CFy + EPS));
7712  Breakdown_file << "%): ";
7713  Breakdown_file.width(11);
7714  Breakdown_file << Inv_CFy;
7715  Breakdown_file << " | Friction (";
7716  Breakdown_file.width(5);
7717  Breakdown_file << SU2_TYPE::Int((Visc_CFy * 100.0) / (Total_CFy + EPS));
7718  Breakdown_file << "%): ";
7719  Breakdown_file.width(11);
7720  Breakdown_file << Visc_CFy;
7721  Breakdown_file << " | Momentum (";
7722  Breakdown_file.width(5);
7723  Breakdown_file << SU2_TYPE::Int((Mnt_CFy * 100.0) / (Total_CFy + EPS));
7724  Breakdown_file << "%): ";
7725  Breakdown_file.width(11);
7726  Breakdown_file << Mnt_CFy << "\n";
7727 
7728  if (nDim == 3) {
7729  Breakdown_file << "Total CFz: ";
7730  Breakdown_file.width(11);
7731  Breakdown_file << Total_CFz;
7732  Breakdown_file << " | Pressure (";
7733  Breakdown_file.width(5);
7734  Breakdown_file << SU2_TYPE::Int((Inv_CFz * 100.0) / (Total_CFz + EPS));
7735  Breakdown_file << "%): ";
7736  Breakdown_file.width(11);
7737  Breakdown_file << Inv_CFz;
7738  Breakdown_file << " | Friction (";
7739  Breakdown_file.width(5);
7740  Breakdown_file << SU2_TYPE::Int((Visc_CFz * 100.0) / (Total_CFz + EPS));
7741  Breakdown_file << "%): ";
7742  Breakdown_file.width(11);
7743  Breakdown_file << Visc_CFz;
7744  Breakdown_file << " | Momentum (";
7745  Breakdown_file.width(5);
7746  Breakdown_file << SU2_TYPE::Int((Mnt_CFz * 100.0) / (Total_CFz + EPS));
7747  Breakdown_file << "%): ";
7748  Breakdown_file.width(11);
7749  Breakdown_file << Mnt_CFz << "\n";
7750  }
7751 
7752  Breakdown_file << "\n" << "\n";
7753 
7754  for (iMarker_Monitoring = 0;
7755  iMarker_Monitoring < config[val_iZone]->GetnMarker_Monitoring();
7756  iMarker_Monitoring++) {
7757 
7758  Breakdown_file << "Surface name: "
7759  << config[val_iZone]->GetMarker_Monitoring_TagBound(
7760  iMarker_Monitoring) << "\n" << "\n";
7761 
7762  Breakdown_file << "Total CL (";
7763  Breakdown_file.width(5);
7764  Breakdown_file
7765  << SU2_TYPE::Int(
7766  (Surface_CL[iMarker_Monitoring] * 100.0)
7767  / (Total_CL + EPS));
7768  Breakdown_file << "%): ";
7769  Breakdown_file.width(11);
7770  Breakdown_file << Surface_CL[iMarker_Monitoring];
7771  Breakdown_file << " | Pressure (";
7772  Breakdown_file.width(5);
7773  Breakdown_file
7774  << SU2_TYPE::Int(
7775  (Surface_CL_Inv[iMarker_Monitoring] * 100.0)
7776  / (Surface_CL[iMarker_Monitoring] + EPS));
7777  Breakdown_file << "%): ";
7778  Breakdown_file.width(11);
7779  Breakdown_file << Surface_CL_Inv[iMarker_Monitoring];
7780  Breakdown_file << " | Friction (";
7781  Breakdown_file.width(5);
7782  Breakdown_file
7783  << SU2_TYPE::Int(
7784  (Surface_CL_Visc[iMarker_Monitoring] * 100.0)
7785  / (Surface_CL[iMarker_Monitoring] + EPS));
7786  Breakdown_file << "%): ";
7787  Breakdown_file.width(11);
7788  Breakdown_file << Surface_CL_Visc[iMarker_Monitoring];
7789  Breakdown_file << " | Momentum (";
7790  Breakdown_file.width(5);
7791  Breakdown_file
7792  << SU2_TYPE::Int(
7793  (Surface_CL_Mnt[iMarker_Monitoring] * 100.0)
7794  / (Surface_CL[iMarker_Monitoring] + EPS));
7795  Breakdown_file << "%): ";
7796  Breakdown_file.width(11);
7797  Breakdown_file << Surface_CL_Mnt[iMarker_Monitoring] << "\n";
7798 
7799  Breakdown_file << "Total CD (";
7800  Breakdown_file.width(5);
7801  Breakdown_file
7802  << SU2_TYPE::Int(
7803  (Surface_CD[iMarker_Monitoring] * 100.0)
7804  / (Total_CD + EPS));
7805  Breakdown_file << "%): ";
7806  Breakdown_file.width(11);
7807  Breakdown_file << Surface_CD[iMarker_Monitoring];
7808  Breakdown_file << " | Pressure (";
7809  Breakdown_file.width(5);
7810  Breakdown_file
7811  << SU2_TYPE::Int(
7812  (Surface_CD_Inv[iMarker_Monitoring] * 100.0)
7813  / (Surface_CD[iMarker_Monitoring] + EPS));
7814  Breakdown_file << "%): ";
7815  Breakdown_file.width(11);
7816  Breakdown_file << Surface_CD_Inv[iMarker_Monitoring];
7817  Breakdown_file << " | Friction (";
7818  Breakdown_file.width(5);
7819  Breakdown_file
7820  << SU2_TYPE::Int(
7821  (Surface_CD_Visc[iMarker_Monitoring] * 100.0)
7822  / (Surface_CD[iMarker_Monitoring] + EPS));
7823  Breakdown_file << "%): ";
7824  Breakdown_file.width(11);
7825  Breakdown_file << Surface_CD_Visc[iMarker_Monitoring];
7826  Breakdown_file << " | Momentum (";
7827  Breakdown_file.width(5);
7828  Breakdown_file
7829  << SU2_TYPE::Int(
7830  (Surface_CD_Mnt[iMarker_Monitoring] * 100.0)
7831  / (Surface_CD[iMarker_Monitoring] + EPS));
7832  Breakdown_file << "%): ";
7833  Breakdown_file.width(11);
7834  Breakdown_file << Surface_CD_Mnt[iMarker_Monitoring] << "\n";
7835 
7836  if (nDim == 3) {
7837  Breakdown_file << "Total CSF (";
7838  Breakdown_file.width(5);
7839  Breakdown_file
7840  << SU2_TYPE::Int(
7841  (Surface_CSF[iMarker_Monitoring] * 100.0)
7842  / (Total_CSF + EPS));
7843  Breakdown_file << "%): ";
7844  Breakdown_file.width(11);
7845  Breakdown_file << Surface_CSF[iMarker_Monitoring];
7846  Breakdown_file << " | Pressure (";
7847  Breakdown_file.width(5);
7848  Breakdown_file
7849  << SU2_TYPE::Int(
7850  (Surface_CSF_Inv[iMarker_Monitoring] * 100.0)
7851  / (Surface_CSF[iMarker_Monitoring] + EPS));
7852  Breakdown_file << "%): ";
7853  Breakdown_file.width(11);
7854  Breakdown_file << Surface_CSF_Inv[iMarker_Monitoring];
7855  Breakdown_file << " | Friction (";
7856  Breakdown_file.width(5);
7857  Breakdown_file
7858  << SU2_TYPE::Int(
7859  (Surface_CSF_Visc[iMarker_Monitoring] * 100.0)
7860  / (Surface_CSF[iMarker_Monitoring] + EPS));
7861  Breakdown_file << "%): ";
7862  Breakdown_file.width(11);
7863  Breakdown_file
7864  << Surface_CSF_Visc[iMarker_Monitoring];
7865  Breakdown_file << " | Momentum (";
7866  Breakdown_file.width(5);
7867  Breakdown_file
7868  << SU2_TYPE::Int(
7869  (Surface_CSF_Mnt[iMarker_Monitoring] * 100.0)
7870  / (Surface_CSF[iMarker_Monitoring] + EPS));
7871  Breakdown_file << "%): ";
7872  Breakdown_file.width(11);
7873  Breakdown_file
7874  << Surface_CSF_Mnt[iMarker_Monitoring] << "\n";
7875  }
7876 
7877  Breakdown_file << "Total CL/CD (";
7878  Breakdown_file.width(5);
7879  Breakdown_file
7880  << SU2_TYPE::Int(
7881  (Surface_CEff[iMarker_Monitoring] * 100.0) / (Total_CEff + EPS));
7882  Breakdown_file << "%): ";
7883  Breakdown_file.width(11);
7884  Breakdown_file << Surface_CEff[iMarker_Monitoring];
7885  Breakdown_file << " | Pressure (";
7886  Breakdown_file.width(5);
7887  Breakdown_file
7888  << SU2_TYPE::Int(
7889  (Surface_CEff_Inv[iMarker_Monitoring] * 100.0)
7890  / (Surface_CEff[iMarker_Monitoring] + EPS));
7891  Breakdown_file << "%): ";
7892  Breakdown_file.width(11);
7893  Breakdown_file << Surface_CEff_Inv[iMarker_Monitoring];
7894  Breakdown_file << " | Friction (";
7895  Breakdown_file.width(5);
7896  Breakdown_file
7897  << SU2_TYPE::Int(
7898  (Surface_CEff_Visc[iMarker_Monitoring] * 100.0)
7899  / (Surface_CEff[iMarker_Monitoring] + EPS));
7900  Breakdown_file << "%): ";
7901  Breakdown_file.width(11);
7902  Breakdown_file
7903  << Surface_CEff_Visc[iMarker_Monitoring];
7904  Breakdown_file << " | Momentum (";
7905  Breakdown_file.width(5);
7906  Breakdown_file
7907  << SU2_TYPE::Int(
7908  (Surface_CEff_Mnt[iMarker_Monitoring] * 100.0)
7909  / (Surface_CEff[iMarker_Monitoring] + EPS));
7910  Breakdown_file << "%): ";
7911  Breakdown_file.width(11);
7912  Breakdown_file
7913  << Surface_CEff_Mnt[iMarker_Monitoring] << "\n";
7914 
7915  if (nDim == 3) {
7916 
7917  Breakdown_file << "Total CMx (";
7918  Breakdown_file.width(5);
7919  Breakdown_file
7920  << SU2_TYPE::Int(
7921  (Surface_CMx[iMarker_Monitoring] * 100.0) / (Total_CMx + EPS));
7922  Breakdown_file << "%): ";
7923  Breakdown_file.width(11);
7924  Breakdown_file << Surface_CMx[iMarker_Monitoring];
7925  Breakdown_file << " | Pressure (";
7926  Breakdown_file.width(5);
7927  Breakdown_file
7928  << SU2_TYPE::Int(
7929  (Surface_CMx_Inv[iMarker_Monitoring] * 100.0)
7930  / (Surface_CMx[iMarker_Monitoring] + EPS));
7931  Breakdown_file << "%): ";
7932  Breakdown_file.width(11);
7933  Breakdown_file << Surface_CMx_Inv[iMarker_Monitoring];
7934  Breakdown_file << " | Friction (";
7935  Breakdown_file.width(5);
7936  Breakdown_file
7937  << SU2_TYPE::Int(
7938  (Surface_CMx_Visc[iMarker_Monitoring] * 100.0)
7939  / (Surface_CMx[iMarker_Monitoring] + EPS));
7940  Breakdown_file << "%): ";
7941  Breakdown_file.width(11);
7942  Breakdown_file
7943  << Surface_CMx_Visc[iMarker_Monitoring];
7944  Breakdown_file << " | Momentum (";
7945  Breakdown_file.width(5);
7946  Breakdown_file
7947  << SU2_TYPE::Int(
7948  (Surface_CMx_Mnt[iMarker_Monitoring] * 100.0)
7949  / (Surface_CMx[iMarker_Monitoring] + EPS));
7950  Breakdown_file << "%): ";
7951  Breakdown_file.width(11);
7952  Breakdown_file
7953  << Surface_CMx_Mnt[iMarker_Monitoring] << "\n";
7954 
7955  Breakdown_file << "Total CMy (";
7956  Breakdown_file.width(5);
7957  Breakdown_file
7958  << SU2_TYPE::Int(
7959  (Surface_CMy[iMarker_Monitoring] * 100.0) / (Total_CMy + EPS));
7960  Breakdown_file << "%): ";
7961  Breakdown_file.width(11);
7962  Breakdown_file << Surface_CMy[iMarker_Monitoring];
7963  Breakdown_file << " | Pressure (";
7964  Breakdown_file.width(5);
7965  Breakdown_file
7966  << SU2_TYPE::Int(
7967  (Surface_CMy_Inv[iMarker_Monitoring] * 100.0)
7968  / (Surface_CMy[iMarker_Monitoring] + EPS));
7969  Breakdown_file << "%): ";
7970  Breakdown_file.width(11);
7971  Breakdown_file << Surface_CMy_Inv[iMarker_Monitoring];
7972  Breakdown_file << " | Friction (";
7973  Breakdown_file.width(5);
7974  Breakdown_file
7975  << SU2_TYPE::Int(
7976  (Surface_CMy_Visc[iMarker_Monitoring] * 100.0)
7977  / (Surface_CMy[iMarker_Monitoring] + EPS));
7978  Breakdown_file << "%): ";
7979  Breakdown_file.width(11);
7980  Breakdown_file
7981  << Surface_CMy_Visc[iMarker_Monitoring];
7982  Breakdown_file << " | Momentum (";
7983  Breakdown_file.width(5);
7984  Breakdown_file
7985  << SU2_TYPE::Int(
7986  (Surface_CMy_Mnt[iMarker_Monitoring] * 100.0)
7987  / (Surface_CMy[iMarker_Monitoring] + EPS));
7988  Breakdown_file << "%): ";
7989  Breakdown_file.width(11);
7990  Breakdown_file
7991  << Surface_CMy_Mnt[iMarker_Monitoring] << "\n";
7992  }
7993 
7994  Breakdown_file << "Total CMz (";
7995  Breakdown_file.width(5);
7996  Breakdown_file
7997  << SU2_TYPE::Int((Surface_CMz[iMarker_Monitoring] * 100.0) / (Total_CMz + EPS));
7998  Breakdown_file << "%): ";
7999  Breakdown_file.width(11);
8000  Breakdown_file << Surface_CMz[iMarker_Monitoring];
8001  Breakdown_file << " | Pressure (";
8002  Breakdown_file.width(5);
8003  Breakdown_file
8004  << SU2_TYPE::Int(
8005  (Surface_CMz_Inv[iMarker_Monitoring] * 100.0)
8006  / (Surface_CMz[iMarker_Monitoring] + EPS));
8007  Breakdown_file << "%): ";
8008  Breakdown_file.width(11);
8009  Breakdown_file << Surface_CMz_Inv[iMarker_Monitoring];
8010  Breakdown_file << " | Friction (";
8011  Breakdown_file.width(5);
8012  Breakdown_file
8013  << SU2_TYPE::Int(
8014  (Surface_CMz_Visc[iMarker_Monitoring] * 100.0)
8015  / (Surface_CMz[iMarker_Monitoring] + EPS));
8016  Breakdown_file << "%): ";
8017  Breakdown_file.width(11);
8018  Breakdown_file
8019  << Surface_CMz_Visc[iMarker_Monitoring];
8020  Breakdown_file << " | Momentum (";
8021  Breakdown_file.width(5);
8022  Breakdown_file
8023  << SU2_TYPE::Int(
8024  (Surface_CMz_Mnt[iMarker_Monitoring] * 100.0)
8025  / (Surface_CMz[iMarker_Monitoring] + EPS));
8026  Breakdown_file << "%): ";
8027  Breakdown_file.width(11);
8028  Breakdown_file
8029  << Surface_CMz_Mnt[iMarker_Monitoring] << "\n";
8030 
8031  Breakdown_file << "Total CFx (";
8032  Breakdown_file.width(5);
8033  Breakdown_file
8034  << SU2_TYPE::Int((Surface_CFx[iMarker_Monitoring] * 100.0) / (Total_CFx + EPS));
8035  Breakdown_file << "%): ";
8036  Breakdown_file.width(11);
8037  Breakdown_file << Surface_CFx[iMarker_Monitoring];
8038  Breakdown_file << " | Pressure (";
8039  Breakdown_file.width(5);
8040  Breakdown_file
8041  << SU2_TYPE::Int(
8042  (Surface_CFx_Inv[iMarker_Monitoring] * 100.0)
8043  / (Surface_CFx[iMarker_Monitoring] + EPS));
8044  Breakdown_file << "%): ";
8045  Breakdown_file.width(11);
8046  Breakdown_file << Surface_CFx_Inv[iMarker_Monitoring];
8047  Breakdown_file << " | Friction (";
8048  Breakdown_file.width(5);
8049  Breakdown_file
8050  << SU2_TYPE::Int(
8051  (Surface_CFx_Visc[iMarker_Monitoring] * 100.0)
8052  / (Surface_CFx[iMarker_Monitoring] + EPS));
8053  Breakdown_file << "%): ";
8054  Breakdown_file.width(11);
8055  Breakdown_file
8056  << Surface_CFx_Visc[iMarker_Monitoring];
8057  Breakdown_file << " | Momentum (";
8058  Breakdown_file.width(5);
8059  Breakdown_file
8060  << SU2_TYPE::Int(
8061  (Surface_CFx_Mnt[iMarker_Monitoring] * 100.0)
8062  / (Surface_CFx[iMarker_Monitoring] + EPS));
8063  Breakdown_file << "%): ";
8064  Breakdown_file.width(11);
8065  Breakdown_file
8066  << Surface_CFx_Mnt[iMarker_Monitoring] << "\n";
8067 
8068  Breakdown_file << "Total CFy (";
8069  Breakdown_file.width(5);
8070  Breakdown_file
8071  << SU2_TYPE::Int((Surface_CFy[iMarker_Monitoring] * 100.0) / (Total_CFy + EPS));
8072  Breakdown_file << "%): ";
8073  Breakdown_file.width(11);
8074  Breakdown_file << Surface_CFy[iMarker_Monitoring];
8075  Breakdown_file << " | Pressure (";
8076  Breakdown_file.width(5);
8077  Breakdown_file
8078  << SU2_TYPE::Int(
8079  (Surface_CFy_Inv[iMarker_Monitoring] * 100.0)
8080  / (Surface_CFy[iMarker_Monitoring] + EPS));
8081  Breakdown_file << "%): ";
8082  Breakdown_file.width(11);
8083  Breakdown_file << Surface_CFy_Inv[iMarker_Monitoring];
8084  Breakdown_file << " | Friction (";
8085  Breakdown_file.width(5);
8086  Breakdown_file
8087  << SU2_TYPE::Int(
8088  (Surface_CFy_Visc[iMarker_Monitoring] * 100.0)
8089  / (Surface_CFy[iMarker_Monitoring] + EPS));
8090  Breakdown_file << "%): ";
8091  Breakdown_file.width(11);
8092  Breakdown_file
8093  << Surface_CFy_Visc[iMarker_Monitoring];
8094  Breakdown_file << " | Momentum (";
8095  Breakdown_file.width(5);
8096  Breakdown_file
8097  << SU2_TYPE::Int(
8098  (Surface_CFy_Mnt[iMarker_Monitoring] * 100.0)
8099  / (Surface_CFy[iMarker_Monitoring] + EPS));
8100  Breakdown_file << "%): ";
8101  Breakdown_file.width(11);
8102  Breakdown_file
8103  << Surface_CFy_Mnt[iMarker_Monitoring] << "\n";
8104 
8105  if (nDim == 3) {
8106  Breakdown_file << "Total CFz (";
8107  Breakdown_file.width(5);
8108  Breakdown_file
8109  << SU2_TYPE::Int(
8110  (Surface_CFz[iMarker_Monitoring] * 100.0) / (Total_CFz + EPS));
8111  Breakdown_file << "%): ";
8112  Breakdown_file.width(11);
8113  Breakdown_file << Surface_CFz[iMarker_Monitoring];
8114  Breakdown_file << " | Pressure (";
8115  Breakdown_file.width(5);
8116  Breakdown_file
8117  << SU2_TYPE::Int(
8118  (Surface_CFz_Inv[iMarker_Monitoring] * 100.0)
8119  / (Surface_CFz[iMarker_Monitoring] + EPS));
8120  Breakdown_file << "%): ";
8121  Breakdown_file.width(11);
8122  Breakdown_file << Surface_CFz_Inv[iMarker_Monitoring];
8123  Breakdown_file << " | Friction (";
8124  Breakdown_file.width(5);
8125  Breakdown_file
8126  << SU2_TYPE::Int(
8127  (Surface_CFz_Visc[iMarker_Monitoring] * 100.0)
8128  / (Surface_CFz[iMarker_Monitoring] + EPS));
8129  Breakdown_file << "%): ";
8130  Breakdown_file.width(11);
8131  Breakdown_file
8132  << Surface_CFz_Visc[iMarker_Monitoring];
8133  Breakdown_file << " | Momentum (";
8134  Breakdown_file.width(5);
8135  Breakdown_file
8136  << SU2_TYPE::Int(
8137  (Surface_CFz_Mnt[iMarker_Monitoring] * 100.0)
8138  / (Surface_CFz[iMarker_Monitoring] + EPS));
8139  Breakdown_file << "%): ";
8140  Breakdown_file.width(11);
8141  Breakdown_file
8142  << Surface_CFz_Mnt[iMarker_Monitoring] << "\n";
8143 
8144  }
8145 
8146  Breakdown_file << "\n";
8147 
8148 
8149  }
8150 
8151  delete [] Surface_CL;
8152  delete [] Surface_CD;
8153  delete [] Surface_CSF;
8154  delete [] Surface_CEff;
8155  delete [] Surface_CFx;
8156  delete [] Surface_CFy;
8157  delete [] Surface_CFz;
8158  delete [] Surface_CMx;
8159  delete [] Surface_CMy;
8160  delete [] Surface_CMz;
8161 
8162  delete [] Surface_CL_Inv;
8163  delete [] Surface_CD_Inv;
8164  delete [] Surface_CSF_Inv;
8165  delete [] Surface_CEff_Inv;
8166  delete [] Surface_CFx_Inv;
8167  delete [] Surface_CFy_Inv;
8168  delete [] Surface_CFz_Inv;
8169  delete [] Surface_CMx_Inv;
8170  delete [] Surface_CMy_Inv;
8171  delete [] Surface_CMz_Inv;
8172 
8173  delete [] Surface_CL_Visc;
8174  delete [] Surface_CD_Visc;
8175  delete [] Surface_CSF_Visc;
8176  delete [] Surface_CEff_Visc;
8177  delete [] Surface_CFx_Visc;
8178  delete [] Surface_CFy_Visc;
8179  delete [] Surface_CFz_Visc;
8180  delete [] Surface_CMx_Visc;
8181  delete [] Surface_CMy_Visc;
8182  delete [] Surface_CMz_Visc;
8183 
8184  delete [] Surface_CL_Mnt;
8185  delete [] Surface_CD_Mnt;
8186  delete [] Surface_CSF_Mnt;
8187  delete [] Surface_CEff_Mnt;
8188  delete [] Surface_CFx_Mnt;
8189  delete [] Surface_CFy_Mnt;
8190  delete [] Surface_CFz_Mnt;
8191  delete [] Surface_CMx_Mnt;
8192  delete [] Surface_CMy_Mnt;
8193  delete [] Surface_CMz_Mnt;
8194 
8195  Breakdown_file.close();
8196 
8197  }
8198 
8199 }
8200 
8201 void COutputLegacy::SetResult_Files(CSolver *****solver_container, CGeometry ****geometry, CConfig **config,
8202  unsigned long iExtIter, unsigned short val_nZone) {
8203 
8204  unsigned short iZone;
8205 
8206  for (iZone = 0; iZone < val_nZone; iZone++) {
8207 
8208  /*--- Flags identifying the types of files to be written. ---*/
8209 
8210  bool Wrt_Vol = config[iZone]->GetWrt_Vol_Sol();
8211  bool Wrt_Srf = config[iZone]->GetWrt_Srf_Sol();
8212  bool Wrt_Csv = config[iZone]->GetWrt_Csv_Sol();
8213 
8214 #ifdef HAVE_MPI
8215  /*--- Do not merge the volume solutions if we are running in parallel.
8216  Force the use of SU2_SOL to merge the volume sols in this case. ---*/
8217 
8219  if (size > SINGLE_NODE) {
8220  Wrt_Vol = false;
8221  Wrt_Srf = false;
8222  }
8223 #endif
8224 
8225  if (rank == MASTER_NODE) cout << endl << "Writing comma-separated values (CSV) surface files." << endl;
8226 
8227  switch (config[iZone]->GetKind_Solver()) {
8228 
8229  case EULER : case NAVIER_STOKES : case RANS :
8230  case INC_EULER : case INC_NAVIER_STOKES : case INC_RANS :
8231  case FEM_EULER : case FEM_NAVIER_STOKES : case FEM_RANS : case FEM_LES :
8232 
8233  if (Wrt_Csv) SetSurfaceCSV_Flow(config[iZone], geometry[iZone][INST_0][MESH_0], solver_container[iZone][INST_0][MESH_0][FLOW_SOL], iExtIter, iZone, INST_0);
8234  break;
8235 
8236 
8239  if (Wrt_Csv) SetSurfaceCSV_Adjoint(config[iZone], geometry[iZone][INST_0][MESH_0], solver_container[iZone][INST_0][MESH_0][ADJFLOW_SOL], solver_container[iZone][INST_0][MESH_0][FLOW_SOL], iExtIter, iZone, INST_0);
8240  break;
8241 
8242  }
8243 
8244  /*--- Get the file output format ---*/
8245 
8246  unsigned short FileFormat = config[iZone]->GetTabular_FileFormat();
8247 
8248  /*--- Merge the node coordinates and connectivity, if necessary. This
8249  is only performed if a volume solution file is requested, and it
8250  is active by default. ---*/
8251 
8252  if (Wrt_Vol || Wrt_Srf) {
8253  if (rank == MASTER_NODE) cout << "Merging connectivities in the Master node." << endl;
8254  MergeConnectivity(config[iZone], geometry[iZone][INST_0][MESH_0], iZone);
8255  }
8256 
8257  /*--- Merge coordinates of all grid nodes (excluding ghost points).
8258  The grid coordinates are always merged and included first in the
8259  restart files. ---*/
8260 
8261  if (rank == MASTER_NODE) cout << "Merging coordinates in the Master node." << endl;
8262  MergeCoordinates(config[iZone], geometry[iZone][INST_0][MESH_0]);
8263 
8264  if ((rank == MASTER_NODE) && (Wrt_Vol || Wrt_Srf)) {
8265  if (FileFormat == TECPLOT_BINARY) {
8266  if (rank == MASTER_NODE) cout << "Writing Tecplot binary volume and surface mesh files." << endl;
8267 // SetTecplotBinary_DomainMesh(config[iZone], geometry[iZone][INST_0][MESH_0], iZone);
8268 // SetTecplotBinary_SurfaceMesh(config[iZone], geometry[iZone][INST_0][MESH_0], iZone);
8269  if (!wrote_base_file)
8270  DeallocateConnectivity(config[iZone], geometry[iZone][INST_0][MESH_0], false);
8271  if (!wrote_surf_file)
8272  DeallocateConnectivity(config[iZone], geometry[iZone][INST_0][MESH_0], wrote_surf_file);
8273  }
8274  }
8275 
8276  /*--- Merge the solution data needed for volume solutions and restarts ---*/
8277 
8278  if (rank == MASTER_NODE) cout << "Merging solution in the Master node." << endl;
8279  MergeSolution(config[iZone], geometry[iZone][INST_0][MESH_0], solver_container[iZone][INST_0][MESH_0], iZone);
8280 
8281  /*--- Write restart, or Tecplot files using the merged data.
8282  This data lives only on the master, and these routines are currently
8283  executed by the master proc alone (as if in serial). ---*/
8284 
8285  if (rank == MASTER_NODE) {
8286 
8287  /*--- Write a native restart file ---*/
8288 
8289  if (rank == MASTER_NODE) cout << "Writing SU2 native restart file." << endl;
8290  SetRestart(config[iZone], geometry[iZone][INST_0][MESH_0], solver_container[iZone][INST_0][MESH_0] , iZone);
8291 
8292  if (Wrt_Vol) {
8293 
8294  switch (FileFormat) {
8295 
8296  case TECPLOT:
8297 
8298  /*--- Write a Tecplot ASCII file ---*/
8299 
8300  if (rank == MASTER_NODE) cout << "Writing Tecplot ASCII file volume solution file." << endl;
8301 // SetTecplotASCII(config[iZone], geometry[iZone][INST_0][MESH_0], solver_container[iZone][INST_0][MESH_0], iZone, val_nZone, false);
8302  DeallocateConnectivity(config[iZone], geometry[iZone][INST_0][MESH_0], false);
8303  break;
8304 
8305 
8306 
8307  case TECPLOT_BINARY:
8308 
8309  /*--- Write a Tecplot binary solution file ---*/
8310 
8311  if (rank == MASTER_NODE) cout << "Writing Tecplot binary volume solution file." << endl;
8312 // SetTecplotBinary_DomainSolution(config[iZone], geometry[iZone][INST_0][MESH_0], iZone);
8313  break;
8314 
8315 
8316  case PARAVIEW:
8317 
8318  /*--- Write a Paraview ASCII file ---*/
8319 
8320  if (rank == MASTER_NODE) cout << "Writing Paraview ASCII volume solution file." << endl;
8321 // SetParaview_ASCII(config[iZone], geometry[iZone][INST_0][MESH_0], iZone, val_nZone, false);
8322  DeallocateConnectivity(config[iZone], geometry[iZone][INST_0][MESH_0], false);
8323  break;
8324 
8325  case PARAVIEW_BINARY:
8326 
8327  /*--- Write a ParaView ASCII file instead for now in serial. ---*/
8328 
8329  if (rank == MASTER_NODE) cout << "ParaView binary volume files not available in this mode." << endl;
8330  if (rank == MASTER_NODE) cout << " Writing ParaView ASCII volume solution file instead." << endl;
8331 // SetParaview_ASCII(config[iZone], geometry[iZone][INST_0][MESH_0], iZone, val_nZone, false);
8332  DeallocateConnectivity(config[iZone], geometry[iZone][INST_0][MESH_0], false);
8333  break;
8334 
8335  default:
8336  break;
8337  }
8338 
8339  }
8340 
8341  if (Wrt_Srf) {
8342 
8343  switch (FileFormat) {
8344 
8345  case TECPLOT:
8346 
8347  /*--- Write a Tecplot ASCII file ---*/
8348 
8349  if (rank == MASTER_NODE) cout << "Writing Tecplot ASCII surface solution file." << endl;
8350 // SetTecplotASCII(config[iZone], geometry[iZone][INST_0][MESH_0], solver_container[iZone][INST_0][MESH_0] , iZone, val_nZone, true);
8351  DeallocateConnectivity(config[iZone], geometry[iZone][INST_0][MESH_0], true);
8352  break;
8353 
8354  case TECPLOT_BINARY:
8355 
8356  /*--- Write a Tecplot binary solution file ---*/
8357 
8358  if (rank == MASTER_NODE) cout << "Writing Tecplot binary surface solution file." << endl;
8359 // SetTecplotBinary_SurfaceSolution(config[iZone], geometry[iZone][INST_0][MESH_0], iZone);
8360  break;
8361 
8362  case PARAVIEW:
8363 
8364  /*--- Write a Paraview ASCII file ---*/
8365 
8366  if (rank == MASTER_NODE) cout << "Writing Paraview ASCII surface solution file." << endl;
8367 // SetParaview_ASCII(config[iZone], geometry[iZone][INST_0][MESH_0], iZone, val_nZone, true);
8368  DeallocateConnectivity(config[iZone], geometry[iZone][INST_0][MESH_0], true);
8369  break;
8370 
8371  case PARAVIEW_BINARY:
8372 
8373  /*--- Write a ParaView ASCII file instead for now in serial. ---*/
8374 
8375  if (rank == MASTER_NODE) cout << "ParaView binary surface files not available in this mode." << endl;
8376  if (rank == MASTER_NODE) cout << " Writing ParaView ASCII surface solution file instead." << endl;
8377 // SetParaview_ASCII(config[iZone], geometry[iZone][INST_0][MESH_0], iZone, val_nZone, true);
8378  DeallocateConnectivity(config[iZone], geometry[iZone][INST_0][MESH_0], true);
8379  break;
8380 
8381  default:
8382  break;
8383  }
8384 
8385  }
8386 
8387  /*--- Release memory needed for merging the solution data. ---*/
8388 
8389  DeallocateCoordinates(config[iZone], geometry[iZone][INST_0][MESH_0]);
8390  DeallocateSolution(config[iZone], geometry[iZone][INST_0][MESH_0]);
8391 
8392  }
8393 
8394  /*--- Final broadcast (informing other procs that the base output
8395  file was written). ---*/
8396 
8397 #ifdef HAVE_MPI
8400 #endif
8401 
8402  }
8403 }
8404 
8405 void COutputLegacy::SetBaselineResult_Files(CSolver ***solver, CGeometry ***geometry, CConfig **config,
8406  unsigned long iExtIter, unsigned short val_nZone) {
8407 
8408  unsigned short iZone, iInst, nInst;
8409 
8410  for (iZone = 0; iZone < val_nZone; iZone++) {
8411 
8412  nInst = config[iZone]->GetnTimeInstances();
8413 
8414  for (iInst = 0; iInst < nInst; iInst++) {
8415 
8416  config[iZone]->SetiInst(iInst);
8417 
8418  /*--- Flags identifying the types of files to be written. ---*/
8419 
8420  bool Wrt_Vol = config[iZone]->GetWrt_Vol_Sol();
8421  if (config[iZone]->GetKind_SU2() == SU2_DOT) { Wrt_Vol = false; }
8422  bool Wrt_Srf = config[iZone]->GetWrt_Srf_Sol();
8423 
8424  /*--- Get the file output format ---*/
8425 
8426  unsigned short FileFormat = config[iZone]->GetTabular_FileFormat();
8427 
8428  /*--- Merge the node coordinates and connectivity if necessary. This
8429  is only performed if a volume solution file is requested, and it
8430  is active by default. ---*/
8431 
8432  if ((Wrt_Vol || Wrt_Srf)) {
8433  if (rank == MASTER_NODE) cout << "Merging connectivities in the Master node." << endl;
8434  MergeConnectivity(config[iZone], geometry[iZone][iInst], iZone);
8435  }
8436 
8437  /*--- Merge the solution data needed for volume solutions and restarts ---*/
8438 
8439  if ((Wrt_Vol || Wrt_Srf)) {
8440  if (rank == MASTER_NODE) cout << "Merging solution in the Master node." << endl;
8441  MergeBaselineSolution(config[iZone], geometry[iZone][iInst], solver[iZone][iInst], iZone);
8442  }
8443 
8444  /*--- Write restart, Tecplot or Paraview files using the merged data.
8445  This data lives only on the master, and these routines are currently
8446  executed by the master proc alone (as if in serial). ---*/
8447 
8448 
8449  if (rank == MASTER_NODE) {
8450 
8451  if (Wrt_Vol) {
8452 
8453  switch (FileFormat) {
8454 
8455  case TECPLOT:
8456 
8457  /*--- Write a Tecplot ASCII file ---*/
8458 
8459  if (rank == MASTER_NODE) cout << "Writing Tecplot ASCII file (volume grid)." << endl;
8460 // SetTecplotASCII(config[iZone], geometry[iZone][iInst], &solver[iZone][iInst], iZone, val_nZone, false);
8461  DeallocateConnectivity(config[iZone], geometry[iZone][iInst], false);
8462  break;
8463 
8464  case TECPLOT_BINARY:
8465 
8466  /*--- Write a Tecplot binary solution file ---*/
8467 
8468  if (rank == MASTER_NODE) cout << "Writing Tecplot Binary file (volume grid)." << endl;
8469 // SetTecplotBinary_DomainMesh(config[iZone], geometry[iZone][iInst], iZone);
8470 // SetTecplotBinary_DomainSolution(config[iZone], geometry[iZone][iInst], iZone);
8471  break;
8472 
8473 
8474  case PARAVIEW:
8475 
8476  /*--- Write a Paraview ASCII file ---*/
8477 
8478  if (rank == MASTER_NODE) cout << "Writing Paraview ASCII file (volume grid)." << endl;
8479 // SetParaview_ASCII(config[iZone], geometry[iZone][iInst], iZone, val_nZone, false);
8480  DeallocateConnectivity(config[iZone], geometry[iZone][iInst], false);
8481  break;
8482 
8483  case PARAVIEW_BINARY:
8484 
8485  /*--- Write a ParaView ASCII file instead for now in serial. ---*/
8486 
8487  if (rank == MASTER_NODE) cout << "ParaView binary volume files not available in this mode." << endl;
8488  if (rank == MASTER_NODE) cout << " Writing ParaView ASCII volume solution file instead." << endl;
8489 // SetParaview_ASCII(config[iZone], geometry[iZone][iInst], iZone, val_nZone, false);
8490  DeallocateConnectivity(config[iZone], geometry[iZone][iInst], false);
8491  break;
8492 
8493  default:
8494  break;
8495  }
8496 
8497  }
8498 
8499  if (Wrt_Srf) {
8500 
8501  switch (FileFormat) {
8502 
8503  case TECPLOT:
8504 
8505  /*--- Write a Tecplot ASCII file ---*/
8506 
8507  if (rank == MASTER_NODE) cout << "Writing Tecplot ASCII file (surface grid)." << endl;
8508 // SetTecplotASCII(config[iZone], geometry[iZone][iInst], &solver[iZone][iInst], iZone, val_nZone, true);
8509  DeallocateConnectivity(config[iZone], geometry[iZone][iInst], true);
8510  break;
8511 
8512  case TECPLOT_BINARY:
8513 
8514  /*--- Write a Tecplot binary solution file ---*/
8515 
8516  if (rank == MASTER_NODE) cout << "Writing Tecplot Binary file (surface grid)." << endl;
8517 // SetTecplotBinary_SurfaceMesh(config[iZone], geometry[iZone][iInst], iZone);
8518 // SetTecplotBinary_SurfaceSolution(config[iZone], geometry[iZone][iInst], iZone);
8519  break;
8520 
8521  case PARAVIEW:
8522 
8523  /*--- Write a Paraview ASCII file ---*/
8524 
8525  if (rank == MASTER_NODE) cout << "Writing Paraview ASCII file (surface grid)." << endl;
8526 // SetParaview_ASCII(config[iZone], geometry[iZone][iInst], iZone, val_nZone, true);
8527  DeallocateConnectivity(config[iZone], geometry[iZone][iInst], true);
8528  break;
8529 
8530  case PARAVIEW_BINARY:
8531 
8532  /*--- Write a ParaView ASCII file instead for now in serial. ---*/
8533 
8534  if (rank == MASTER_NODE) cout << "ParaView binary surface files not available in this mode." << endl;
8535  if (rank == MASTER_NODE) cout << " Writing ParaView ASCII surface solution file instead." << endl;
8536 // SetParaview_ASCII(config[iZone], geometry[iZone][iInst], iZone, val_nZone, true);
8537  DeallocateConnectivity(config[iZone], geometry[iZone][iInst], true);
8538  break;
8539 
8540  default:
8541  break;
8542  }
8543  }
8544 
8545  if (FileFormat == TECPLOT_BINARY) {
8546  if (!wrote_base_file)
8547  DeallocateConnectivity(config[iZone], geometry[iZone][iInst], false);
8548  if (!wrote_surf_file)
8549  DeallocateConnectivity(config[iZone], geometry[iZone][iInst], wrote_surf_file);
8550  }
8551 
8552  if (Wrt_Vol || Wrt_Srf)
8553  DeallocateSolution(config[iZone], geometry[iZone][iInst]);
8554  }
8555 
8556 
8557 
8558  /*--- Final broadcast (informing other procs that the base output
8559  file was written). ---*/
8560 
8561 #ifdef HAVE_MPI
8563 #endif
8564 
8565  }
8566 
8567  }
8568 }
8569 
8570 void COutputLegacy::SetMesh_Files(CGeometry **geometry, CConfig **config, unsigned short val_nZone, bool new_file, bool su2_file) {
8571 
8572  char cstr[MAX_STRING_SIZE], out_file[MAX_STRING_SIZE];
8573  unsigned short iZone;
8574  ofstream output_file;
8575  string str;
8576 
8577  /*--- Read the name of the output and input file ---*/
8578 
8579  if (su2_file) {
8580  if (rank == MASTER_NODE) {
8581  str = config[ZONE_0]->GetMesh_Out_FileName();
8582  strcpy (out_file, str.c_str());
8583  strcpy (cstr, out_file);
8584  output_file.precision(15);
8585  output_file.open(cstr, ios::out);
8586  if (val_nZone > 1) {
8587  output_file << "NZONE= " << val_nZone << endl;
8588  }
8589  }
8590  }
8591 
8592  for (iZone = 0; iZone < val_nZone; iZone++) {
8593 
8594  /*--- Flags identifying the types of files to be written. ---*/
8595 
8596  bool Wrt_Vol = config[iZone]->GetVisualize_Volume_Def();
8597  bool Wrt_Srf = config[iZone]->GetVisualize_Surface_Def();
8598  //bool Wrt_Crd = config[iZone]->GetWrt_Crd_Sol();
8599 
8600  /*--- Merge the node coordinates and connectivity if necessary. This
8601  is only performed if a volume solution file is requested, and it
8602  is active by default. ---*/
8603 
8604  if (rank == MASTER_NODE) cout <<"Merging grid connectivity." << endl;
8605  MergeConnectivity(config[iZone], geometry[iZone], iZone);
8606 
8607  /*--- Merge coordinates of all grid nodes (excluding ghost points).
8608  The grid coordinates are always merged and included first in the
8609  restart files. ---*/
8610 
8611  if (rank == MASTER_NODE) cout <<"Merging grid coordinates." << endl;
8612  MergeCoordinates(config[iZone], geometry[iZone]);
8613 
8614  /*--- Write restart, Tecplot or Paraview files using the merged data.
8615  This data lives only on the master, and these routines are currently
8616  executed by the master proc alone (as if in serial). ---*/
8617 
8618  if (rank == MASTER_NODE) {
8619 
8620  if (Wrt_Vol) {
8621 
8622  if (rank == MASTER_NODE) cout <<"Writing volume mesh file." << endl;
8623 
8624 // /*--- Write a Tecplot ASCII file ---*/
8625 
8627 // else if (config[iZone]->GetTabular_FileFormat() == PARAVIEW_BINARY) {
8628 // if (rank == MASTER_NODE) cout <<"Writing ASCII paraview volume mesh file by default." << endl;
8630 // }
8632 // else if (config[iZone]->GetTabular_FileFormat() == TECPLOT_BINARY) {
8633 // if (rank == MASTER_NODE) cout <<"Writing ASCII tecplot volume mesh file by default." << endl;
8635 // }
8636 
8637  }
8638 
8639  if (Wrt_Srf) {
8640 
8641  if (rank == MASTER_NODE) cout <<"Writing surface mesh file." << endl;
8642 
8643  /*--- Write a Tecplot ASCII file ---*/
8644 
8645 // if (config[iZone]->GetOutput_FileFormat() == PARAVIEW) SetParaview_MeshASCII(config[iZone], geometry[iZone], iZone, val_nZone, true, new_file);
8646 // else if (config[iZone]->GetOutput_FileFormat() == PARAVIEW_BINARY) {
8647 // if (rank == MASTER_NODE) cout <<"Writing ASCII paraview surface mesh file by default." << endl;
8648 // SetParaview_MeshASCII(config[iZone], geometry[iZone], iZone, val_nZone, true, new_file);
8649 // }
8650 // else if (config[iZone]->GetOutput_FileFormat() == TECPLOT) SetTecplotASCII_Mesh(config[iZone], geometry[iZone], iZone, true, new_file);
8651 // else if (config[iZone]->GetOutput_FileFormat() == TECPLOT_BINARY) {
8652 // if (rank == MASTER_NODE) cout <<"Writing ASCII tecplot surface mesh file by default." << endl;
8653 // SetTecplotASCII_Mesh(config[iZone], geometry[iZone], iZone, true, new_file);
8654 // }
8655 
8656  }
8657 
8658  /*--- Write a .su2 ASCII file ---*/
8659 
8660  if (su2_file) {
8661 
8662  if (rank == MASTER_NODE) cout <<"Writing .su2 file." << endl;
8663 
8664 // SetSU2_MeshASCII(config[iZone], geometry[iZone], iZone, output_file);
8665 
8666  /*--- Write an stl surface file ---*/
8667 
8668  if (rank == MASTER_NODE) cout <<"Writing .stl surface file." << endl;
8669 
8670 // SetSTL_MeshASCII(config[iZone], geometry[iZone]);
8671 
8672  }
8673 
8674  /*--- Write a binary file with the grid coordinates alone. ---*/
8675 
8676 // if (Wrt_Crd) {
8677 // if (rank == MASTER_NODE) cout <<"Writing .dat binary coordinates file." << endl;
8678 // WriteCoordinates_Binary(config[iZone], geometry[iZone], iZone);
8679 // }
8680 
8681 
8682  /*--- Deallocate connectivity ---*/
8683 
8684  DeallocateConnectivity(config[iZone], geometry[iZone], true);
8685  DeallocateConnectivity(config[iZone], geometry[iZone], false);
8686  DeallocateCoordinates(config[iZone], geometry[iZone]);
8687 
8688  }
8689 
8690  /*--- Final broadcast (informing other procs that the base output
8691  file was written). ---*/
8692 
8693 #ifdef HAVE_MPI
8695 #endif
8696 
8697  /*--- Write an csv surface file, done in parallel ---*/
8698 
8699  if (rank == MASTER_NODE) cout <<"Writing .csv surface file." << endl;
8700 
8701 // if (su2_file) SetCSV_MeshASCII(config[iZone], geometry[iZone]);
8702 
8703  }
8704 
8705  if (rank == MASTER_NODE) {
8706  if (su2_file){
8707  output_file.close();
8708  }
8709  }
8710 }
8711 
8712 void COutputLegacy::SpecialOutput_SpanLoad(CSolver *solver, CGeometry *geometry, CConfig *config, bool output) {
8713 
8714  short iSection, nSection;
8715  unsigned long iVertex, iPoint, Trailing_Point;
8716  su2double *Plane_P0, *Plane_P0_, *Plane_Normal, *Plane_Normal_, *CPressure,
8717  Force[3], ForceInviscid[3], MomentInviscid[3] =
8718  { 0.0, 0.0, 0.0 }, MomentDist[3] = { 0.0, 0.0, 0.0 }, RefDensity,
8719  RefPressure, RefArea, *Velocity_Inf, Gas_Constant, Mach2Vel,
8720  Mach_Motion, Gamma, RefVel2 = 0.0, factor, NDPressure, *Origin,
8721  RefLength, Alpha, CL_Inv,
8722  Xcoord_LeadingEdge = 0.0, Ycoord_LeadingEdge = 0.0, Zcoord_LeadingEdge = 0.0,
8723  Xcoord_TrailingEdge = 0.0, Ycoord_TrailingEdge = 0.0, Zcoord_TrailingEdge = 0.0,
8724  Xcoord_LeadingEdge_ = 0.0,
8725  Xcoord_TrailingEdge_ = 0.0, Ycoord_TrailingEdge_ = 0.0, Zcoord_TrailingEdge_ = 0.0,
8726  MaxDistance, Distance, Chord, Aux, Dihedral_Trailing;
8727 
8728  su2double B, Y, C_L, C_L0, Elliptic_Spanload;
8729 
8730  vector<su2double> Xcoord_Airfoil, Ycoord_Airfoil, Zcoord_Airfoil,
8731  CPressure_Airfoil;
8732  vector<su2double> Xcoord_Airfoil_, Ycoord_Airfoil_, Zcoord_Airfoil_,
8733  CPressure_Airfoil_;
8734  string Marker_Tag, Slice_Filename, Slice_Ext;
8735  ofstream Cp_File;
8736  unsigned short iDim;
8737 
8738  bool dynamic_grid = config->GetDynamic_Grid();
8739 
8740  Plane_P0 = new su2double[3];
8741  Plane_P0_ = new su2double[3];
8742  Plane_Normal = new su2double[3];
8743  Plane_Normal_ = new su2double[3];
8744  CPressure = new su2double[geometry->GetnPoint()];
8745 
8746  if ((rank == MASTER_NODE) && (output)) {
8747  cout << endl << "Writing the spanload file (load_distribution.dat).";
8748  }
8749 
8750  /*--- Compute some reference quantities and necessary values ---*/
8751 
8752  RefDensity = solver->GetDensity_Inf();
8753  RefPressure = solver->GetPressure_Inf();
8754  RefArea = config->GetRefArea();
8755  Velocity_Inf = solver->GetVelocity_Inf();
8756  Gamma = config->GetGamma();
8757  Origin = config->GetRefOriginMoment(0);
8758  RefLength = config->GetRefLength();
8759  Alpha = config->GetAoA() * PI_NUMBER / 180.0;
8760 
8761  if (dynamic_grid) {
8762  Gas_Constant = config->GetGas_ConstantND();
8763  Mach2Vel = sqrt(
8764  Gamma * Gas_Constant * config->GetTemperature_FreeStreamND());
8765  Mach_Motion = config->GetMach_Motion();
8766  RefVel2 = (Mach_Motion * Mach2Vel) * (Mach_Motion * Mach2Vel);
8767  } else {
8768  RefVel2 = 0.0;
8769  for (iDim = 0; iDim < geometry->GetnDim(); iDim++)
8770  RefVel2 += Velocity_Inf[iDim] * Velocity_Inf[iDim];
8771  }
8772  factor = 1.0 / (0.5 * RefDensity * RefArea * RefVel2);
8773 
8774  if (geometry->GetnDim() == 3) {
8775 
8776  /*--- Copy the pressure to an auxiliar structure ---*/
8777 
8778  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
8779  CPressure[iPoint] = (solver->GetNodes()->GetPressure(iPoint)
8780  - RefPressure) * factor * RefArea;
8781  }
8782 
8783  nSection = config->GetnLocationStations();
8784 
8785  for (iSection = 0; iSection < nSection; iSection++) {
8786 
8787  /*--- Read the values from the config file ---*/
8788 
8789  Plane_Normal[0] = 0.0; Plane_P0[0] = 0.0;
8790  Plane_Normal[1] = 0.0; Plane_P0[1] = 0.0;
8791  Plane_Normal[2] = 0.0; Plane_P0[2] = 0.0;
8792 
8793  if (config->GetGeo_Description() == FUSELAGE) {
8794  Plane_Normal[0] = 1.0;
8795  Plane_P0[0] = config->GetLocationStations(iSection);
8796  }
8797  else if (config->GetGeo_Description() == NACELLE) {
8798  Plane_Normal[0] = 0.0;
8799  Plane_Normal[1] = -sin(config->GetLocationStations(iSection)*PI_NUMBER/180.0);
8800  Plane_Normal[2] = cos(config->GetLocationStations(iSection)*PI_NUMBER/180.0);
8801 
8802  /*--- Apply tilt angle to the plane ---*/
8803 
8804  su2double Tilt_Angle = config->GetNacelleLocation(3)*PI_NUMBER/180;
8805  su2double Plane_NormalX_Tilt = Plane_Normal[0]*cos(Tilt_Angle) + Plane_Normal[2]*sin(Tilt_Angle);
8806  su2double Plane_NormalY_Tilt = Plane_Normal[1];
8807  su2double Plane_NormalZ_Tilt = Plane_Normal[2]*cos(Tilt_Angle) - Plane_Normal[0]*sin(Tilt_Angle);
8808 
8809  /*--- Apply toe angle to the plane ---*/
8810 
8811  su2double Toe_Angle = config->GetNacelleLocation(4)*PI_NUMBER/180;
8812  su2double Plane_NormalX_Tilt_Toe = Plane_NormalX_Tilt*cos(Toe_Angle) - Plane_NormalY_Tilt*sin(Toe_Angle);
8813  su2double Plane_NormalY_Tilt_Toe = Plane_NormalX_Tilt*sin(Toe_Angle) + Plane_NormalY_Tilt*cos(Toe_Angle);
8814  su2double Plane_NormalZ_Tilt_Toe = Plane_NormalZ_Tilt;
8815 
8816  /*--- Update normal vector ---*/
8817 
8818  Plane_Normal[0] = Plane_NormalX_Tilt_Toe;
8819  Plane_Normal[1] = Plane_NormalY_Tilt_Toe;
8820  Plane_Normal[2] = Plane_NormalZ_Tilt_Toe;
8821 
8822  }
8823  else {
8824  Plane_Normal[1] = 1.0;
8825  Plane_P0[1] = config->GetLocationStations(iSection);
8826  }
8827 
8828  /*--- Compute the airfoil sections (note that we feed in the Cp) ---*/
8829 
8830  geometry->ComputeAirfoil_Section(Plane_P0, Plane_Normal, -1E6, 1E6, -1E6, 1E6, -1E6, 1E6,
8831  CPressure, Xcoord_Airfoil, Ycoord_Airfoil, Zcoord_Airfoil,
8832  CPressure_Airfoil, true, config);
8833 
8834  if ((rank == MASTER_NODE) && (Xcoord_Airfoil.size() == 0)) {
8835  if ((config->GetGeo_Description() == FUSELAGE) || (config->GetGeo_Description() == WING))
8836  cout << endl << "Please check the config file, the section (" << Plane_P0[0] <<", " << Plane_P0[1] <<", " << Plane_P0[2] << ") has not been detected." << endl;
8837  if (config->GetGeo_Description() == NACELLE)
8838  cout << endl << "Please check the config file, the section (" << Plane_Normal[0] <<", " << Plane_Normal[1] <<", " << Plane_Normal[2] << ") has not been detected." << endl;
8839  }
8840 
8841 
8842  /*--- Compute dihedral using a step in the station value ---*/
8843 
8844  Plane_P0_[0] = 0.0; Plane_Normal_[0] = 0.0;
8845  Plane_P0_[1] = 0.0; Plane_Normal_[1] = 0.0;
8846  Plane_P0_[2] = 0.0; Plane_Normal_[2] = 0.0;
8847 
8848  if (config->GetGeo_Description() == FUSELAGE) {
8849  Plane_Normal_[0] = 1.0;
8850  if (iSection == 0) Plane_P0_[0] = config->GetLocationStations(iSection) + 0.01;
8851  else Plane_P0_[0] = config->GetLocationStations(iSection) - 0.01;
8852  }
8853  else if (config->GetGeo_Description() == NACELLE) {
8854  if (iSection == 0) {
8855  Plane_Normal_[0] = 0.0;
8856  Plane_Normal_[1] = -sin((config->GetLocationStations(iSection) + 0.01)*PI_NUMBER/180.0);
8857  Plane_Normal_[2] = cos((config->GetLocationStations(iSection) + 0.01)*PI_NUMBER/180.0);
8858 
8859  /*--- Apply tilt angle to the plane ---*/
8860 
8861  su2double Tilt_Angle = config->GetNacelleLocation(3)*PI_NUMBER/180;
8862  su2double Plane_NormalX_Tilt = Plane_Normal[0]*cos(Tilt_Angle) + Plane_Normal[2]*sin(Tilt_Angle);
8863  su2double Plane_NormalY_Tilt = Plane_Normal[1];
8864  su2double Plane_NormalZ_Tilt = Plane_Normal[2]*cos(Tilt_Angle) - Plane_Normal[0]*sin(Tilt_Angle);
8865 
8866  /*--- Apply toe angle to the plane ---*/
8867 
8868  su2double Toe_Angle = config->GetNacelleLocation(4)*PI_NUMBER/180;
8869  su2double Plane_NormalX_Tilt_Toe = Plane_NormalX_Tilt*cos(Toe_Angle) - Plane_NormalY_Tilt*sin(Toe_Angle);
8870  su2double Plane_NormalY_Tilt_Toe = Plane_NormalX_Tilt*sin(Toe_Angle) + Plane_NormalY_Tilt*cos(Toe_Angle);
8871  su2double Plane_NormalZ_Tilt_Toe = Plane_NormalZ_Tilt;
8872 
8873  /*--- Update normal vector ---*/
8874 
8875  Plane_Normal[0] = Plane_NormalX_Tilt_Toe;
8876  Plane_Normal[1] = Plane_NormalY_Tilt_Toe;
8877  Plane_Normal[2] = Plane_NormalZ_Tilt_Toe;
8878 
8879  }
8880  else {
8881  Plane_Normal_[0] = 0.0;
8882  Plane_Normal_[1] = -sin((config->GetLocationStations(iSection) - 0.01)*PI_NUMBER/180.0);
8883  Plane_Normal_[2] = cos((config->GetLocationStations(iSection) - 0.01)*PI_NUMBER/180.0);
8884 
8885  /*--- Apply tilt angle to the plane ---*/
8886 
8887  su2double Tilt_Angle = config->GetNacelleLocation(3)*PI_NUMBER/180;
8888  su2double Plane_NormalX_Tilt = Plane_Normal[0]*cos(Tilt_Angle) + Plane_Normal[2]*sin(Tilt_Angle);
8889  su2double Plane_NormalY_Tilt = Plane_Normal[1];
8890  su2double Plane_NormalZ_Tilt = Plane_Normal[2]*cos(Tilt_Angle) - Plane_Normal[0]*sin(Tilt_Angle);
8891 
8892  /*--- Apply toe angle to the plane ---*/
8893 
8894  su2double Toe_Angle = config->GetNacelleLocation(4)*PI_NUMBER/180;
8895  su2double Plane_NormalX_Tilt_Toe = Plane_NormalX_Tilt*cos(Toe_Angle) - Plane_NormalY_Tilt*sin(Toe_Angle);
8896  su2double Plane_NormalY_Tilt_Toe = Plane_NormalX_Tilt*sin(Toe_Angle) + Plane_NormalY_Tilt*cos(Toe_Angle);
8897  su2double Plane_NormalZ_Tilt_Toe = Plane_NormalZ_Tilt;
8898 
8899  /*--- Update normal vector ---*/
8900 
8901  Plane_Normal[0] = Plane_NormalX_Tilt_Toe;
8902  Plane_Normal[1] = Plane_NormalY_Tilt_Toe;
8903  Plane_Normal[2] = Plane_NormalZ_Tilt_Toe;
8904 
8905  }
8906  }
8907  else {
8908  Plane_Normal_[1] = 1.0;
8909  if (iSection == 0) Plane_P0_[1] = config->GetLocationStations(iSection) + 0.01;
8910  else Plane_P0_[1] = config->GetLocationStations(iSection) - 0.01;
8911  }
8912 
8913  geometry->ComputeAirfoil_Section(Plane_P0_, Plane_Normal_, -1E6, 1E6, -1E6, 1E6, -1E6, 1E6,
8914  CPressure, Xcoord_Airfoil_, Ycoord_Airfoil_, Zcoord_Airfoil_,
8915  CPressure_Airfoil_, true, config);
8916 
8917  /*--- Output the pressure on each section (tecplot format) ---*/
8918 
8919  if ((rank == MASTER_NODE) && (Xcoord_Airfoil.size() != 0)) {
8920 
8921  /*--- Find leading and trailing edge ---*/
8922 
8923  Xcoord_LeadingEdge = 1E6; Xcoord_TrailingEdge = -1E6;
8924  for (iVertex = 0; iVertex < Xcoord_Airfoil.size(); iVertex++) {
8925  if (Xcoord_Airfoil[iVertex] < Xcoord_LeadingEdge) {
8926  Xcoord_LeadingEdge = Xcoord_Airfoil[iVertex];
8927  Ycoord_LeadingEdge = Ycoord_Airfoil[iVertex];
8928  Zcoord_LeadingEdge = Zcoord_Airfoil[iVertex];
8929  }
8930  if (Xcoord_Airfoil[iVertex] > Xcoord_TrailingEdge) {
8931  Xcoord_TrailingEdge = Xcoord_Airfoil[iVertex];
8932  Ycoord_TrailingEdge = Ycoord_Airfoil[iVertex];
8933  Zcoord_TrailingEdge = Zcoord_Airfoil[iVertex];
8934  }
8935  }
8936 
8937  Chord = (Xcoord_TrailingEdge-Xcoord_LeadingEdge);
8938 
8939  /*--- Compute dihedral ---*/
8940 
8941  Xcoord_LeadingEdge_ = 1E6; Xcoord_TrailingEdge_ = -1E6;
8942  for (iVertex = 0; iVertex < Xcoord_Airfoil_.size(); iVertex++) {
8943  if (Xcoord_Airfoil_[iVertex] < Xcoord_LeadingEdge_) {
8944  Xcoord_LeadingEdge_ = Xcoord_Airfoil_[iVertex];
8945  }
8946  if (Xcoord_Airfoil_[iVertex] > Xcoord_TrailingEdge_) {
8947  Xcoord_TrailingEdge_ = Xcoord_Airfoil_[iVertex];
8948  Ycoord_TrailingEdge_ = Ycoord_Airfoil_[iVertex];
8949  Zcoord_TrailingEdge_ = Zcoord_Airfoil_[iVertex];
8950  }
8951  }
8952 
8953  if (iSection == 0) {
8954  Dihedral_Trailing = atan((Zcoord_TrailingEdge_ - Zcoord_TrailingEdge) / (Ycoord_TrailingEdge_ - Ycoord_TrailingEdge))*180/PI_NUMBER;
8955  }
8956  else {
8957  Dihedral_Trailing = atan((Zcoord_TrailingEdge - Zcoord_TrailingEdge_) / (Ycoord_TrailingEdge - Ycoord_TrailingEdge_))*180/PI_NUMBER;
8958  }
8959 
8960  /*--- Write Cp at each section (tecplot format) ---*/
8961 
8962  if (output) {
8963 
8964  ofstream Cp_File;
8965 
8966  if (iSection == 0) {
8967  Cp_File.open("cp_sections.dat", ios::out);
8968  Cp_File << "TITLE = \"Airfoil sections\"" << endl;
8969  Cp_File << "VARIABLES = \"x/c\",\"C<sub>p</sub>\",\"x\",\"y\",\"z\",\"y/c\",\"z/c\"" << endl;
8970  } else
8971  Cp_File.open("cp_sections.dat", ios::app);
8972 
8973  if (config->GetGeo_Description() == NACELLE) {
8974  su2double theta_deg = atan2(Plane_Normal[1], -Plane_Normal[2])/PI_NUMBER*180 + 180;
8975  Cp_File << "ZONE T=\"Theta = " << theta_deg << " deg\", I= " << Xcoord_Airfoil.size() << ", F=POINT" << "\n";
8976  }
8977  else {
8978  if (config->GetSystemMeasurements() == SI) Cp_File << "ZONE T=\"y = " << Plane_P0[1] << " m\", I= "
8979  << Xcoord_Airfoil.size() << ", F=POINT" << "\n";
8980 
8981  if (config->GetSystemMeasurements() == US) Cp_File << "ZONE T=\"y = " << Plane_P0[1]*12.0 << " in\", I= "
8982  << Xcoord_Airfoil.size() << ", F=POINT" << "\n";
8983  }
8984 
8985 
8986 
8987  /*--- Coordinates and pressure value ---*/
8988 
8989  for (iVertex = 0; iVertex < Xcoord_Airfoil.size(); iVertex++) {
8990 
8991  su2double XCoord = Xcoord_Airfoil[iVertex];
8992  su2double YCoord = Ycoord_Airfoil[iVertex];
8993  su2double ZCoord = Zcoord_Airfoil[iVertex];
8994 
8995  /*--- Undo the transformation based on the Theta angle ---*/
8996 
8997  if (config->GetGeo_Description() == NACELLE) {
8998  su2double theta_deg = atan2(Plane_Normal[1],-Plane_Normal[2])/PI_NUMBER*180 + 180;
8999  su2double Angle = theta_deg*PI_NUMBER/180 - 0.5*PI_NUMBER;
9000 
9001  XCoord = Xcoord_Airfoil[iVertex] + config->GetNacelleLocation(0);
9002  YCoord = (Ycoord_Airfoil[iVertex]*cos(Angle) - Zcoord_Airfoil[iVertex]*sin(Angle)) + config->GetNacelleLocation(1);
9003  ZCoord = (Zcoord_Airfoil[iVertex]*cos(Angle) + Ycoord_Airfoil[iVertex]*sin(Angle)) + config->GetNacelleLocation(2);
9004 
9005  }
9006 
9007  if (config->GetSystemMeasurements() == US) {
9008  Cp_File << (Xcoord_Airfoil[iVertex] - Xcoord_LeadingEdge) / Chord << " " << CPressure_Airfoil[iVertex]
9009  << " " << XCoord * 12.0 << " " << YCoord * 12.0 << " " << ZCoord * 12.0
9010  << " " << (Ycoord_Airfoil[iVertex] - Ycoord_LeadingEdge) / Chord << " " << (Zcoord_Airfoil[iVertex] - Zcoord_LeadingEdge) / Chord << "\n";
9011  }
9012  else {
9013  Cp_File << (Xcoord_Airfoil[iVertex] - Xcoord_LeadingEdge) / Chord << " " << CPressure_Airfoil[iVertex]
9014  << " " << XCoord << " " << YCoord << " " << ZCoord
9015  << " " << (Ycoord_Airfoil[iVertex] - Ycoord_LeadingEdge) / Chord << " " << (Zcoord_Airfoil[iVertex] - Zcoord_LeadingEdge) / Chord << "\n";
9016  }
9017 
9018  }
9019 
9020  Cp_File.close();
9021 
9022  }
9023 
9024  /*--- Compute load distribution ---*/
9025 
9026  ForceInviscid[0] = 0.0; ForceInviscid[1] = 0.0; ForceInviscid[2] = 0.0; MomentInviscid[1] = 0.0;
9027 
9028  for (iVertex = 0; iVertex < Xcoord_Airfoil.size() - 1; iVertex++) {
9029 
9030  NDPressure = 0.5 * (CPressure_Airfoil[iVertex] + CPressure_Airfoil[iVertex + 1]);
9031 
9032  Force[0] = -(Zcoord_Airfoil[iVertex + 1] - Zcoord_Airfoil[iVertex]) * NDPressure;
9033  Force[1] = 0.0;
9034  Force[2] = (Xcoord_Airfoil[iVertex + 1] - Xcoord_Airfoil[iVertex]) * NDPressure;
9035 
9036  ForceInviscid[0] += Force[0];
9037  ForceInviscid[1] += Force[1];
9038  ForceInviscid[2] += Force[2];
9039 
9040  MomentDist[0] = 0.5 * (Xcoord_Airfoil[iVertex] + Xcoord_Airfoil[iVertex + 1]) - Origin[0];
9041  MomentDist[1] = 0.5 * (Ycoord_Airfoil[iVertex] + Ycoord_Airfoil[iVertex + 1]) - Origin[1];
9042  MomentDist[2] = 0.5 * (Zcoord_Airfoil[iVertex] + Zcoord_Airfoil[iVertex + 1]) - Origin[3];
9043 
9044  MomentInviscid[1] += (Force[0] * MomentDist[2] - Force[2] * MomentDist[0]) / RefLength;
9045 
9046  }
9047 
9048  /*--- Compute local chord, for the nondimensionalization ---*/
9049 
9050  MaxDistance = 0.0; Trailing_Point = 0;
9051 
9052  for (iVertex = 1; iVertex < Xcoord_Airfoil.size(); iVertex++) {
9053 
9054  Distance = sqrt(pow(Xcoord_Airfoil[iVertex] - Xcoord_Airfoil[Trailing_Point], 2.0) +
9055  pow(Ycoord_Airfoil[iVertex] - Ycoord_Airfoil[Trailing_Point], 2.0) +
9056  pow(Zcoord_Airfoil[iVertex] - Zcoord_Airfoil[Trailing_Point], 2.0));
9057 
9058  if (MaxDistance < Distance) { MaxDistance = Distance; }
9059 
9060  }
9061 
9062  Chord = MaxDistance;
9063 
9064  CL_Inv = cos(Dihedral_Trailing * PI_NUMBER / 180.0) * fabs( -ForceInviscid[0] * sin(Alpha) + ForceInviscid[2] * cos(Alpha) )/ Chord;
9065 
9066  /*--- Compute sectional lift at the root ---*/
9067 
9068  B = 2.0*config->GetSemiSpan();
9069  RefArea = config->GetRefArea();
9070  C_L = solver->GetTotal_CL();
9071  C_L0 = 8.0*C_L*RefArea/(B*PI_NUMBER);
9072  Y = Ycoord_Airfoil[0];
9073  Aux = Y/(0.5*B);
9074  Elliptic_Spanload = (C_L0 / RefLength) * sqrt(fabs(1.0-Aux*Aux));
9075 
9076 
9077  /*--- Write load distribution ---*/
9078 
9079  if (output) {
9080 
9081  ofstream Load_File;
9082  if (iSection == 0) {
9083 
9084  if ((config->GetTabular_FileFormat() == TAB_CSV)) {
9085  Load_File.open("load_distribution.csv", ios::out);
9086  Load_File << "\"Percent Semispan\",\"Sectional C_L\",\"Spanload (c C_L / c_ref) \",\"Elliptic Spanload\"" << endl;
9087  }
9088  else {
9089  Load_File.open("load_distribution.dat", ios::out);
9090  Load_File << "TITLE = \"Load distribution\"" << endl;
9091  Load_File << "VARIABLES = \"Percent Semispan\",\"Sectional C<sub>L</sub>\",\"Spanload (c C<sub>L</sub> / c<sub>ref</sub>) \",\"Elliptic Spanload\"" << endl;
9092  Load_File << "ZONE T=\"Wing load distribution\"" << endl;
9093  }
9094  } else {
9095  if ((config->GetTabular_FileFormat() == TAB_CSV)) Load_File.open("load_distribution.csv", ios::app);
9096  else Load_File.open("load_distribution.dat", ios::app);
9097  }
9098 
9099 
9100  /*--- CL and spanload ---*/
9101 
9102  if ((config->GetTabular_FileFormat() == TAB_CSV))
9103  Load_File << 100.0*Ycoord_Airfoil[0]/(0.5*B) << ", " << CL_Inv << ", " << Chord*CL_Inv / RefLength <<", " << Elliptic_Spanload << endl;
9104  else
9105  Load_File << 100.0*Ycoord_Airfoil[0]/(0.5*B) << " " << CL_Inv << " " << Chord*CL_Inv / RefLength <<" " << Elliptic_Spanload << endl;
9106 
9107  Load_File.close();
9108 
9109  }
9110 
9111  }
9112 
9113  }
9114 
9115  }
9116 
9117  /*--- Delete dynamically allocated memory ---*/
9118 
9119  delete[] Plane_P0;
9120  delete[] Plane_P0_;
9121  delete[] Plane_Normal;
9122  delete[] Plane_Normal_;
9123  delete[] CPressure;
9124 
9125 }
9126 
9127 
9128 void COutputLegacy::SetCp_InverseDesign(CSolver *solver_container, CGeometry *geometry, CConfig *config, unsigned long iExtIter) {
9129 
9130  unsigned short iMarker, icommas, Boundary, iDim;
9131  unsigned long iVertex, iPoint, (*Point2Vertex)[2], nPointLocal = 0, nPointGlobal = 0;
9132  su2double XCoord, YCoord, ZCoord, Pressure, PressureCoeff = 0, Cp, CpTarget, *Normal = NULL, Area, PressDiff;
9133  bool *PointInDomain;
9134  string text_line, surfCp_filename;
9135  ifstream Surface_file;
9136  char buffer[50], cstr[200];
9137 
9138 
9139  nPointLocal = geometry->GetnPoint();
9140 #ifdef HAVE_MPI
9141  SU2_MPI::Allreduce(&nPointLocal, &nPointGlobal, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD);
9142 #else
9143  nPointGlobal = nPointLocal;
9144 #endif
9145 
9146  Point2Vertex = new unsigned long[nPointGlobal][2];
9147  PointInDomain = new bool[nPointGlobal];
9148 
9149  for (iPoint = 0; iPoint < nPointGlobal; iPoint ++)
9150  PointInDomain[iPoint] = false;
9151 
9152  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
9153  Boundary = config->GetMarker_All_KindBC(iMarker);
9154 
9155  if ((Boundary == EULER_WALL ) ||
9156  (Boundary == HEAT_FLUX ) ||
9157  (Boundary == ISOTHERMAL ) ||
9158  (Boundary == NEARFIELD_BOUNDARY)) {
9159  for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
9160 
9161  /*--- The Pressure file uses the global numbering ---*/
9162 
9163 #ifndef HAVE_MPI
9164  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
9165 #else
9166  iPoint = geometry->node[geometry->vertex[iMarker][iVertex]->GetNode()]->GetGlobalIndex();
9167 #endif
9168 
9169  if (geometry->vertex[iMarker][iVertex]->GetNode() < geometry->GetnPointDomain()) {
9170  Point2Vertex[iPoint][0] = iMarker;
9171  Point2Vertex[iPoint][1] = iVertex;
9172  PointInDomain[iPoint] = true;
9173  solver_container->SetCPressureTarget(iMarker, iVertex, 0.0);
9174  }
9175 
9176  }
9177  }
9178  }
9179 
9180  /*--- Prepare to read the surface pressure files (CSV) ---*/
9181 
9182  surfCp_filename = "TargetCp";
9183  strcpy (cstr, surfCp_filename.c_str());
9184 
9185  /*--- Write file name with extension if unsteady or steady ---*/
9186 
9187  if ((config->GetTime_Marching() && config->GetTime_Domain()) ||
9188  (config->GetTime_Marching() == HARMONIC_BALANCE)) {
9189  if ((SU2_TYPE::Int(iExtIter) >= 0) && (SU2_TYPE::Int(iExtIter) < 10)) SPRINTF (buffer, "_0000%d.dat", SU2_TYPE::Int(iExtIter));
9190  if ((SU2_TYPE::Int(iExtIter) >= 10) && (SU2_TYPE::Int(iExtIter) < 100)) SPRINTF (buffer, "_000%d.dat", SU2_TYPE::Int(iExtIter));
9191  if ((SU2_TYPE::Int(iExtIter) >= 100) && (SU2_TYPE::Int(iExtIter) < 1000)) SPRINTF (buffer, "_00%d.dat", SU2_TYPE::Int(iExtIter));
9192  if ((SU2_TYPE::Int(iExtIter) >= 1000) && (SU2_TYPE::Int(iExtIter) < 10000)) SPRINTF (buffer, "_0%d.dat", SU2_TYPE::Int(iExtIter));
9193  if (SU2_TYPE::Int(iExtIter) >= 10000) SPRINTF (buffer, "_%d.dat", SU2_TYPE::Int(iExtIter));
9194  }
9195  else
9196  SPRINTF (buffer, ".dat");
9197 
9198  strcat (cstr, buffer);
9199 
9200  /*--- Read the surface pressure file ---*/
9201 
9202  string::size_type position;
9203 
9204  Surface_file.open(cstr, ios::in);
9205 
9206  if (!(Surface_file.fail())) {
9207 
9208  getline(Surface_file, text_line);
9209 
9210  while (getline(Surface_file, text_line)) {
9211  for (icommas = 0; icommas < 50; icommas++) {
9212  position = text_line.find( ",", 0 );
9213  if (position!=string::npos) text_line.erase (position,1);
9214  }
9215  stringstream point_line(text_line);
9216 
9217  if (geometry->GetnDim() == 2) point_line >> iPoint >> XCoord >> YCoord >> Pressure >> PressureCoeff;
9218  if (geometry->GetnDim() == 3) point_line >> iPoint >> XCoord >> YCoord >> ZCoord >> Pressure >> PressureCoeff;
9219 
9220  if (PointInDomain[iPoint]) {
9221 
9222  /*--- Find the vertex for the Point and Marker ---*/
9223 
9224  iMarker = Point2Vertex[iPoint][0];
9225  iVertex = Point2Vertex[iPoint][1];
9226 
9227  solver_container->SetCPressureTarget(iMarker, iVertex, PressureCoeff);
9228 
9229  }
9230 
9231  }
9232 
9233  Surface_file.close();
9234 
9235  }
9236 
9237  /*--- Compute the pressure difference ---*/
9238 
9239  PressDiff = 0.0;
9240  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
9241  Boundary = config->GetMarker_All_KindBC(iMarker);
9242 
9243  if ((Boundary == EULER_WALL ) ||
9244  (Boundary == HEAT_FLUX ) ||
9245  (Boundary == ISOTHERMAL ) ||
9246  (Boundary == NEARFIELD_BOUNDARY)) {
9247  for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
9248 
9249  Normal = geometry->vertex[iMarker][iVertex]->GetNormal();
9250 
9251  Cp = solver_container->GetCPressure(iMarker, iVertex);
9252  CpTarget = solver_container->GetCPressureTarget(iMarker, iVertex);
9253 
9254  Area = 0.0;
9255  for (iDim = 0; iDim < geometry->GetnDim(); iDim++)
9256  Area += Normal[iDim]*Normal[iDim];
9257  Area = sqrt(Area);
9258 
9259  PressDiff += Area * (CpTarget - Cp) * (CpTarget - Cp);
9260  }
9261 
9262  }
9263  }
9264 
9265 #ifdef HAVE_MPI
9266  su2double MyPressDiff = PressDiff; PressDiff = 0.0;
9267  SU2_MPI::Allreduce(&MyPressDiff, &PressDiff, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
9268 #endif
9269 
9270  /*--- Update the total Cp difference coeffient ---*/
9271 
9272  solver_container->SetTotal_CpDiff(PressDiff);
9273 
9274  delete [] Point2Vertex;
9275  delete [] PointInDomain;
9276 
9277 }
9278 
9279 void COutputLegacy::SetHeatFlux_InverseDesign(CSolver *solver_container, CGeometry *geometry, CConfig *config, unsigned long iExtIter) {
9280 
9281  unsigned short iMarker, icommas, Boundary, iDim;
9282  unsigned long iVertex, iPoint, (*Point2Vertex)[2], nPointLocal = 0, nPointGlobal = 0;
9283  su2double XCoord, YCoord, ZCoord, PressureCoeff, HeatFlux = 0.0, HeatFluxDiff, HeatFluxTarget, *Normal = NULL, Area,
9284  Pressure, Cf;
9285  bool *PointInDomain;
9286  string text_line, surfHeatFlux_filename;
9287  ifstream Surface_file;
9288  char buffer[50], cstr[200];
9289 
9290 
9291  nPointLocal = geometry->GetnPoint();
9292 #ifdef HAVE_MPI
9293  SU2_MPI::Allreduce(&nPointLocal, &nPointGlobal, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD);
9294 #else
9295  nPointGlobal = nPointLocal;
9296 #endif
9297 
9298  Point2Vertex = new unsigned long[nPointGlobal][2];
9299  PointInDomain = new bool[nPointGlobal];
9300 
9301  for (iPoint = 0; iPoint < nPointGlobal; iPoint ++)
9302  PointInDomain[iPoint] = false;
9303 
9304  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
9305  Boundary = config->GetMarker_All_KindBC(iMarker);
9306 
9307  if ((Boundary == EULER_WALL ) ||
9308  (Boundary == HEAT_FLUX ) ||
9309  (Boundary == ISOTHERMAL ) ||
9310  (Boundary == NEARFIELD_BOUNDARY)) {
9311  for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
9312 
9313  /*--- The Pressure file uses the global numbering ---*/
9314 
9315 #ifndef HAVE_MPI
9316  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
9317 #else
9318  iPoint = geometry->node[geometry->vertex[iMarker][iVertex]->GetNode()]->GetGlobalIndex();
9319 #endif
9320 
9321  if (geometry->vertex[iMarker][iVertex]->GetNode() < geometry->GetnPointDomain()) {
9322  Point2Vertex[iPoint][0] = iMarker;
9323  Point2Vertex[iPoint][1] = iVertex;
9324  PointInDomain[iPoint] = true;
9325  solver_container->SetHeatFluxTarget(iMarker, iVertex, 0.0);
9326  }
9327  }
9328  }
9329  }
9330 
9331  /*--- Prepare to read the surface pressure files (CSV) ---*/
9332 
9333  surfHeatFlux_filename = "TargetHeatFlux";
9334  strcpy (cstr, surfHeatFlux_filename.c_str());
9335 
9336  /*--- Write file name with extension if unsteady or steady ---*/
9337 
9338  if ((config->GetTime_Marching() && config->GetTime_Domain()) ||
9339  (config->GetTime_Marching() == HARMONIC_BALANCE)) {
9340  if ((SU2_TYPE::Int(iExtIter) >= 0) && (SU2_TYPE::Int(iExtIter) < 10)) SPRINTF (buffer, "_0000%d.dat", SU2_TYPE::Int(iExtIter));
9341  if ((SU2_TYPE::Int(iExtIter) >= 10) && (SU2_TYPE::Int(iExtIter) < 100)) SPRINTF (buffer, "_000%d.dat", SU2_TYPE::Int(iExtIter));
9342  if ((SU2_TYPE::Int(iExtIter) >= 100) && (SU2_TYPE::Int(iExtIter) < 1000)) SPRINTF (buffer, "_00%d.dat", SU2_TYPE::Int(iExtIter));
9343  if ((SU2_TYPE::Int(iExtIter) >= 1000) && (SU2_TYPE::Int(iExtIter) < 10000)) SPRINTF (buffer, "_0%d.dat", SU2_TYPE::Int(iExtIter));
9344  if (SU2_TYPE::Int(iExtIter) >= 10000) SPRINTF (buffer, "_%d.dat", SU2_TYPE::Int(iExtIter));
9345  }
9346  else
9347  SPRINTF (buffer, ".dat");
9348 
9349  strcat (cstr, buffer);
9350 
9351  /*--- Read the surface pressure file ---*/
9352 
9353  string::size_type position;
9354 
9355  Surface_file.open(cstr, ios::in);
9356 
9357  if (!(Surface_file.fail())) {
9358 
9359  getline(Surface_file, text_line);
9360 
9361  while (getline(Surface_file, text_line)) {
9362  for (icommas = 0; icommas < 50; icommas++) {
9363  position = text_line.find( ",", 0 );
9364  if (position!=string::npos) text_line.erase (position,1);
9365  }
9366  stringstream point_line(text_line);
9367 
9368  if (geometry->GetnDim() == 2) point_line >> iPoint >> XCoord >> YCoord >> Pressure >> PressureCoeff >> Cf >> HeatFlux;
9369  if (geometry->GetnDim() == 3) point_line >> iPoint >> XCoord >> YCoord >> ZCoord >> Pressure >> PressureCoeff >> Cf >> HeatFlux;
9370 
9371  if (PointInDomain[iPoint]) {
9372 
9373  /*--- Find the vertex for the Point and Marker ---*/
9374 
9375  iMarker = Point2Vertex[iPoint][0];
9376  iVertex = Point2Vertex[iPoint][1];
9377 
9378  solver_container->SetHeatFluxTarget(iMarker, iVertex, HeatFlux);
9379 
9380  }
9381 
9382  }
9383 
9384  Surface_file.close();
9385  }
9386 
9387  /*--- Compute the pressure difference ---*/
9388 
9389  HeatFluxDiff = 0.0;
9390  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
9391  Boundary = config->GetMarker_All_KindBC(iMarker);
9392 
9393  if ((Boundary == EULER_WALL ) ||
9394  (Boundary == HEAT_FLUX ) ||
9395  (Boundary == ISOTHERMAL ) ||
9396  (Boundary == NEARFIELD_BOUNDARY)) {
9397  for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
9398 
9399  Normal = geometry->vertex[iMarker][iVertex]->GetNormal();
9400 
9401  HeatFlux = solver_container->GetHeatFlux(iMarker, iVertex);
9402  HeatFluxTarget = solver_container->GetHeatFluxTarget(iMarker, iVertex);
9403 
9404  Area = 0.0;
9405  for (iDim = 0; iDim < geometry->GetnDim(); iDim++)
9406  Area += Normal[iDim]*Normal[iDim];
9407  Area = sqrt(Area);
9408 
9409  HeatFluxDiff += Area * (HeatFluxTarget - HeatFlux) * (HeatFluxTarget - HeatFlux);
9410 
9411  }
9412 
9413  }
9414  }
9415 
9416 #ifdef HAVE_MPI
9417  su2double MyHeatFluxDiff = HeatFluxDiff; HeatFluxDiff = 0.0;
9418  SU2_MPI::Allreduce(&MyHeatFluxDiff, &HeatFluxDiff, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
9419 #endif
9420 
9421  /*--- Update the total HeatFlux difference coeffient ---*/
9422 
9423  solver_container->SetTotal_HeatFluxDiff(HeatFluxDiff);
9424 
9425  delete [] Point2Vertex;
9426  delete [] PointInDomain;
9427 
9428 }
9429 
9430 void COutputLegacy::SpecialOutput_SonicBoom(CSolver *solver, CGeometry *geometry, CConfig *config, bool output) {
9431 
9432  ofstream EquivArea_file, FuncGrad_file;
9433  unsigned short iMarker = 0, iDim;
9434  short *AzimuthalAngle = NULL;
9435  su2double Gamma, auxXCoord, auxYCoord, auxZCoord, InverseDesign = 0.0, DeltaX, Coord_i, Coord_j, jp1Coord, *Coord = NULL, MeanFuntion,
9436  *Face_Normal = NULL, auxArea, auxPress, Mach, Beta, R_Plane, Pressure_Inf,
9437  ModVelocity_Inf, Velocity_Inf[3], factor, *Xcoord = NULL, *Ycoord = NULL, *Zcoord = NULL,
9438  *Pressure = NULL, *FaceArea = NULL, *EquivArea = NULL, *TargetArea = NULL, *NearFieldWeight = NULL,
9439  *Weight = NULL, jFunction, jp1Function;
9440  unsigned long jVertex, iVertex, iPoint, nVertex_NearField = 0, auxPoint,
9441  *IdPoint = NULL, *IdDomain = NULL, auxDomain;
9442  unsigned short iPhiAngle;
9443  ofstream NearFieldEA_file; ifstream TargetEA_file;
9444 
9445  su2double XCoordBegin_OF = config->GetEA_IntLimit(0);
9446  su2double XCoordEnd_OF = config->GetEA_IntLimit(1);
9447 
9448  unsigned short nDim = geometry->GetnDim();
9449  su2double AoA = -(config->GetAoA()*PI_NUMBER/180.0);
9450  su2double EAScaleFactor = config->GetEA_ScaleFactor(); // The EA Obj. Func. should be ~ force based Obj. Func.
9451 
9452  Mach = config->GetMach();
9453  Gamma = config->GetGamma();
9454  Beta = sqrt(Mach*Mach-1.0);
9455  R_Plane = fabs(config->GetEA_IntLimit(2));
9456  Pressure_Inf = config->GetPressure_FreeStreamND();
9457  Velocity_Inf[0] = config->GetVelocity_FreeStreamND()[0];
9458  Velocity_Inf[1] = config->GetVelocity_FreeStreamND()[1];
9459  Velocity_Inf[2] = config->GetVelocity_FreeStreamND()[2];
9460  ModVelocity_Inf = 0;
9461  for (iDim = 0; iDim < 3; iDim++)
9462  ModVelocity_Inf += Velocity_Inf[iDim] * Velocity_Inf[iDim];
9463 
9464  factor = 4.0*sqrt(2.0*Beta*R_Plane) / (Gamma*Pressure_Inf*Mach*Mach);
9465 
9466  if (rank == MASTER_NODE) cout << endl << "Writing Equivalent Area files.";
9467 
9468 #ifndef HAVE_MPI
9469 
9470  /*--- Compute the total number of points on the near-field ---*/
9471 
9472  nVertex_NearField = 0;
9473  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++)
9474  if (config->GetMarker_All_KindBC(iMarker) == NEARFIELD_BOUNDARY)
9475  for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
9476  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
9477  Face_Normal = geometry->vertex[iMarker][iVertex]->GetNormal();
9478  Coord = geometry->node[iPoint]->GetCoord();
9479 
9480  /*--- Using Face_Normal(z), and Coord(z) we identify only a surface,
9481  note that there are 2 NEARFIELD_BOUNDARY surfaces ---*/
9482 
9483  if ((Face_Normal[nDim-1] > 0.0) && (Coord[nDim-1] < 0.0)) nVertex_NearField ++;
9484  }
9485 
9486  /*--- Create an array with all the coordinates, points, pressures, face area,
9487  equivalent area, and nearfield weight ---*/
9488 
9489  Xcoord = new su2double[nVertex_NearField];
9490  Ycoord = new su2double[nVertex_NearField];
9491  Zcoord = new su2double[nVertex_NearField];
9492  AzimuthalAngle = new short[nVertex_NearField];
9493  IdPoint = new unsigned long[nVertex_NearField];
9494  IdDomain = new unsigned long[nVertex_NearField];
9495  Pressure = new su2double[nVertex_NearField];
9496  FaceArea = new su2double[nVertex_NearField];
9497  EquivArea = new su2double[nVertex_NearField];
9498  TargetArea = new su2double[nVertex_NearField];
9499  NearFieldWeight = new su2double[nVertex_NearField];
9500  Weight = new su2double[nVertex_NearField];
9501 
9502  /*--- Copy the boundary information to an array ---*/
9503 
9504  nVertex_NearField = 0;
9505  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++)
9506  if (config->GetMarker_All_KindBC(iMarker) == NEARFIELD_BOUNDARY)
9507  for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
9508  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
9509  Face_Normal = geometry->vertex[iMarker][iVertex]->GetNormal();
9510  Coord = geometry->node[iPoint]->GetCoord();
9511 
9512  if ((Face_Normal[nDim-1] > 0.0) && (Coord[nDim-1] < 0.0)) {
9513 
9514  IdPoint[nVertex_NearField] = iPoint;
9515  Xcoord[nVertex_NearField] = geometry->node[iPoint]->GetCoord(0);
9516  Ycoord[nVertex_NearField] = geometry->node[iPoint]->GetCoord(1);
9517 
9518  if (nDim ==2) {
9519  AzimuthalAngle[nVertex_NearField] = 0;
9520  }
9521 
9522  if (nDim == 3) {
9523  Zcoord[nVertex_NearField] = geometry->node[iPoint]->GetCoord(2);
9524 
9525  /*--- Rotate the nearfield cylinder (AoA) only 3D ---*/
9526 
9527  su2double YcoordRot = Ycoord[nVertex_NearField];
9528  su2double ZcoordRot = Xcoord[nVertex_NearField]*sin(AoA) + Zcoord[nVertex_NearField]*cos(AoA);
9529 
9530  /*--- Compute the Azimuthal angle (resolution of degress in the Azimuthal angle)---*/
9531 
9532  su2double AngleDouble; short AngleInt;
9533  AngleDouble = fabs(atan(-YcoordRot/ZcoordRot)*180.0/PI_NUMBER);
9534 
9535  /*--- Fix an azimuthal line due to misalignments of the near-field ---*/
9536 
9537  su2double FixAzimuthalLine = config->GetFixAzimuthalLine();
9538 
9539  if ((AngleDouble >= FixAzimuthalLine - 0.1) && (AngleDouble <= FixAzimuthalLine + 0.1)) AngleDouble = FixAzimuthalLine - 0.1;
9540 
9541  AngleInt = SU2_TYPE::Short(floor(AngleDouble + 0.5));
9542  if (AngleInt >= 0) AzimuthalAngle[nVertex_NearField] = AngleInt;
9543  else AzimuthalAngle[nVertex_NearField] = 180 + AngleInt;
9544  }
9545 
9546  if (AzimuthalAngle[nVertex_NearField] <= 60) {
9547  Pressure[nVertex_NearField] = solver->GetNodes()->GetPressure(iPoint);
9548  FaceArea[nVertex_NearField] = fabs(Face_Normal[nDim-1]);
9549  nVertex_NearField ++;
9550  }
9551 
9552  }
9553  }
9554 
9555 #else
9556 
9557  int nProcessor;
9558  SU2_MPI::Comm_size(MPI_COMM_WORLD, &nProcessor);
9559 
9560  unsigned long nLocalVertex_NearField = 0, MaxLocalVertex_NearField = 0;
9561  int iProcessor;
9562 
9563  unsigned long *Buffer_Receive_nVertex = NULL;
9564  if (rank == MASTER_NODE) {
9565  Buffer_Receive_nVertex = new unsigned long [nProcessor];
9566  }
9567 
9568  /*--- Compute the total number of points of the near-field ghost nodes ---*/
9569 
9570  nLocalVertex_NearField = 0;
9571  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++)
9572  if (config->GetMarker_All_KindBC(iMarker) == NEARFIELD_BOUNDARY)
9573  for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
9574  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
9575  Face_Normal = geometry->vertex[iMarker][iVertex]->GetNormal();
9576  Coord = geometry->node[iPoint]->GetCoord();
9577 
9578  if (geometry->node[iPoint]->GetDomain())
9579  if ((Face_Normal[nDim-1] > 0.0) && (Coord[nDim-1] < 0.0))
9580  nLocalVertex_NearField ++;
9581  }
9582 
9583  unsigned long *Buffer_Send_nVertex = new unsigned long [1];
9584  Buffer_Send_nVertex[0] = nLocalVertex_NearField;
9585 
9586  /*--- Send Near-Field vertex information --*/
9587 
9588  SU2_MPI::Allreduce(&nLocalVertex_NearField, &nVertex_NearField, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD);
9589  SU2_MPI::Allreduce(&nLocalVertex_NearField, &MaxLocalVertex_NearField, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
9590  SU2_MPI::Gather(Buffer_Send_nVertex, 1, MPI_UNSIGNED_LONG, Buffer_Receive_nVertex, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
9591  delete [] Buffer_Send_nVertex;
9592 
9593  su2double *Buffer_Send_Xcoord = new su2double[MaxLocalVertex_NearField];
9594  su2double *Buffer_Send_Ycoord = new su2double[MaxLocalVertex_NearField];
9595  su2double *Buffer_Send_Zcoord = new su2double[MaxLocalVertex_NearField];
9596  unsigned long *Buffer_Send_IdPoint = new unsigned long [MaxLocalVertex_NearField];
9597  su2double *Buffer_Send_Pressure = new su2double [MaxLocalVertex_NearField];
9598  su2double *Buffer_Send_FaceArea = new su2double[MaxLocalVertex_NearField];
9599 
9600  su2double *Buffer_Receive_Xcoord = NULL;
9601  su2double *Buffer_Receive_Ycoord = NULL;
9602  su2double *Buffer_Receive_Zcoord = NULL;
9603  unsigned long *Buffer_Receive_IdPoint = NULL;
9604  su2double *Buffer_Receive_Pressure = NULL;
9605  su2double *Buffer_Receive_FaceArea = NULL;
9606 
9607  if (rank == MASTER_NODE) {
9608  Buffer_Receive_Xcoord = new su2double[nProcessor*MaxLocalVertex_NearField];
9609  Buffer_Receive_Ycoord = new su2double[nProcessor*MaxLocalVertex_NearField];
9610  Buffer_Receive_Zcoord = new su2double[nProcessor*MaxLocalVertex_NearField];
9611  Buffer_Receive_IdPoint = new unsigned long[nProcessor*MaxLocalVertex_NearField];
9612  Buffer_Receive_Pressure = new su2double[nProcessor*MaxLocalVertex_NearField];
9613  Buffer_Receive_FaceArea = new su2double[nProcessor*MaxLocalVertex_NearField];
9614  }
9615 
9616  unsigned long nBuffer_Xcoord = MaxLocalVertex_NearField;
9617  unsigned long nBuffer_Ycoord = MaxLocalVertex_NearField;
9618  unsigned long nBuffer_Zcoord = MaxLocalVertex_NearField;
9619  unsigned long nBuffer_IdPoint = MaxLocalVertex_NearField;
9620  unsigned long nBuffer_Pressure = MaxLocalVertex_NearField;
9621  unsigned long nBuffer_FaceArea = MaxLocalVertex_NearField;
9622 
9623  for (iVertex = 0; iVertex < MaxLocalVertex_NearField; iVertex++) {
9624  Buffer_Send_IdPoint[iVertex] = 0; Buffer_Send_Pressure[iVertex] = 0.0;
9625  Buffer_Send_FaceArea[iVertex] = 0.0; Buffer_Send_Xcoord[iVertex] = 0.0;
9626  Buffer_Send_Ycoord[iVertex] = 0.0; Buffer_Send_Zcoord[iVertex] = 0.0;
9627  }
9628 
9629  /*--- Copy coordinates, index points, and pressures to the auxiliar vector --*/
9630 
9631  nLocalVertex_NearField = 0;
9632  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++)
9633  if (config->GetMarker_All_KindBC(iMarker) == NEARFIELD_BOUNDARY)
9634  for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
9635  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
9636  Face_Normal = geometry->vertex[iMarker][iVertex]->GetNormal();
9637  Coord = geometry->node[iPoint]->GetCoord();
9638 
9639  if (geometry->node[iPoint]->GetDomain())
9640  if ((Face_Normal[nDim-1] > 0.0) && (Coord[nDim-1] < 0.0)) {
9641  Buffer_Send_IdPoint[nLocalVertex_NearField] = iPoint;
9642  Buffer_Send_Xcoord[nLocalVertex_NearField] = geometry->node[iPoint]->GetCoord(0);
9643  Buffer_Send_Ycoord[nLocalVertex_NearField] = geometry->node[iPoint]->GetCoord(1);
9644  Buffer_Send_Zcoord[nLocalVertex_NearField] = geometry->node[iPoint]->GetCoord(2);
9645  Buffer_Send_Pressure[nLocalVertex_NearField] = solver->GetNodes()->GetPressure(iPoint);
9646  Buffer_Send_FaceArea[nLocalVertex_NearField] = fabs(Face_Normal[nDim-1]);
9647  nLocalVertex_NearField++;
9648  }
9649  }
9650 
9651  /*--- Send all the information --*/
9652 
9653  SU2_MPI::Gather(Buffer_Send_Xcoord, nBuffer_Xcoord, MPI_DOUBLE, Buffer_Receive_Xcoord, nBuffer_Xcoord, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
9654  SU2_MPI::Gather(Buffer_Send_Ycoord, nBuffer_Ycoord, MPI_DOUBLE, Buffer_Receive_Ycoord, nBuffer_Ycoord, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
9655  SU2_MPI::Gather(Buffer_Send_Zcoord, nBuffer_Zcoord, MPI_DOUBLE, Buffer_Receive_Zcoord, nBuffer_Zcoord, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
9656  SU2_MPI::Gather(Buffer_Send_IdPoint, nBuffer_IdPoint, MPI_UNSIGNED_LONG, Buffer_Receive_IdPoint, nBuffer_IdPoint, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
9657  SU2_MPI::Gather(Buffer_Send_Pressure, nBuffer_Pressure, MPI_DOUBLE, Buffer_Receive_Pressure, nBuffer_Pressure, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
9658  SU2_MPI::Gather(Buffer_Send_FaceArea, nBuffer_FaceArea, MPI_DOUBLE, Buffer_Receive_FaceArea, nBuffer_FaceArea, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
9659  delete [] Buffer_Send_Xcoord;
9660  delete [] Buffer_Send_Ycoord;
9661  delete [] Buffer_Send_Zcoord;
9662  delete [] Buffer_Send_IdPoint;
9663  delete [] Buffer_Send_Pressure;
9664  delete [] Buffer_Send_FaceArea;
9665 
9666  if (rank == MASTER_NODE) {
9667 
9668  Xcoord = new su2double[nVertex_NearField];
9669  Ycoord = new su2double[nVertex_NearField];
9670  Zcoord = new su2double[nVertex_NearField];
9671  AzimuthalAngle = new short[nVertex_NearField];
9672  IdPoint = new unsigned long[nVertex_NearField];
9673  IdDomain = new unsigned long[nVertex_NearField];
9674  Pressure = new su2double[nVertex_NearField];
9675  FaceArea = new su2double[nVertex_NearField];
9676  EquivArea = new su2double[nVertex_NearField];
9677  TargetArea = new su2double[nVertex_NearField];
9678  NearFieldWeight = new su2double[nVertex_NearField];
9679  Weight = new su2double[nVertex_NearField];
9680 
9681  nVertex_NearField = 0;
9682  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++)
9683  for (iVertex = 0; iVertex < Buffer_Receive_nVertex[iProcessor]; iVertex++) {
9684  Xcoord[nVertex_NearField] = Buffer_Receive_Xcoord[iProcessor*MaxLocalVertex_NearField+iVertex];
9685  Ycoord[nVertex_NearField] = Buffer_Receive_Ycoord[iProcessor*MaxLocalVertex_NearField+iVertex];
9686 
9687  if (nDim == 2) {
9688  AzimuthalAngle[nVertex_NearField] = 0;
9689  }
9690 
9691  if (nDim == 3) {
9692  Zcoord[nVertex_NearField] = Buffer_Receive_Zcoord[iProcessor*MaxLocalVertex_NearField+iVertex];
9693 
9694  /*--- Rotate the nearfield cylinder ---*/
9695 
9696  su2double YcoordRot = Ycoord[nVertex_NearField];
9697  su2double ZcoordRot = Xcoord[nVertex_NearField]*sin(AoA) + Zcoord[nVertex_NearField]*cos(AoA);
9698 
9699  /*--- Compute the Azimuthal angle ---*/
9700 
9701  su2double AngleDouble; short AngleInt;
9702  AngleDouble = fabs(atan(-YcoordRot/ZcoordRot)*180.0/PI_NUMBER);
9703 
9704  /*--- Fix an azimuthal line due to misalignments of the near-field ---*/
9705 
9706  su2double FixAzimuthalLine = config->GetFixAzimuthalLine();
9707 
9708  if ((AngleDouble >= FixAzimuthalLine - 0.1) && (AngleDouble <= FixAzimuthalLine + 0.1))
9709  AngleDouble = FixAzimuthalLine - 0.1;
9710 
9711  AngleInt = SU2_TYPE::Short(floor(AngleDouble + 0.5));
9712 
9713  if (AngleInt >= 0) AzimuthalAngle[nVertex_NearField] = AngleInt;
9714  else AzimuthalAngle[nVertex_NearField] = 180 + AngleInt;
9715  }
9716 
9717  if (AzimuthalAngle[nVertex_NearField] <= 60) {
9718  IdPoint[nVertex_NearField] = Buffer_Receive_IdPoint[iProcessor*MaxLocalVertex_NearField+iVertex];
9719  Pressure[nVertex_NearField] = Buffer_Receive_Pressure[iProcessor*MaxLocalVertex_NearField+iVertex];
9720  FaceArea[nVertex_NearField] = Buffer_Receive_FaceArea[iProcessor*MaxLocalVertex_NearField+iVertex];
9721  IdDomain[nVertex_NearField] = iProcessor;
9722  nVertex_NearField++;
9723  }
9724 
9725  }
9726 
9727  delete [] Buffer_Receive_nVertex;
9728 
9729  delete [] Buffer_Receive_Xcoord;
9730  delete [] Buffer_Receive_Ycoord;
9731  delete [] Buffer_Receive_Zcoord;
9732  delete [] Buffer_Receive_IdPoint;
9733  delete [] Buffer_Receive_Pressure;
9734  delete [] Buffer_Receive_FaceArea;
9735 
9736  }
9737 
9738 #endif
9739 
9740  if (rank == MASTER_NODE) {
9741 
9742  vector<short> PhiAngleList;
9743  vector<short>::iterator IterPhiAngleList;
9744 
9745  for (iVertex = 0; iVertex < nVertex_NearField; iVertex++)
9746  PhiAngleList.push_back(AzimuthalAngle[iVertex]);
9747 
9748  sort( PhiAngleList.begin(), PhiAngleList.end());
9749  IterPhiAngleList = unique( PhiAngleList.begin(), PhiAngleList.end());
9750  PhiAngleList.resize( IterPhiAngleList - PhiAngleList.begin() );
9751 
9752  /*--- Create vectors and distribute the values among the different PhiAngle queues ---*/
9753 
9754  vector<vector<su2double> > Xcoord_PhiAngle; Xcoord_PhiAngle.resize(PhiAngleList.size());
9755  vector<vector<su2double> > Ycoord_PhiAngle; Ycoord_PhiAngle.resize(PhiAngleList.size());
9756  vector<vector<su2double> > Zcoord_PhiAngle; Zcoord_PhiAngle.resize(PhiAngleList.size());
9757  vector<vector<unsigned long> > IdPoint_PhiAngle; IdPoint_PhiAngle.resize(PhiAngleList.size());
9758  vector<vector<unsigned long> > IdDomain_PhiAngle; IdDomain_PhiAngle.resize(PhiAngleList.size());
9759  vector<vector<su2double> > Pressure_PhiAngle; Pressure_PhiAngle.resize(PhiAngleList.size());
9760  vector<vector<su2double> > FaceArea_PhiAngle; FaceArea_PhiAngle.resize(PhiAngleList.size());
9761  vector<vector<su2double> > EquivArea_PhiAngle; EquivArea_PhiAngle.resize(PhiAngleList.size());
9762  vector<vector<su2double> > TargetArea_PhiAngle; TargetArea_PhiAngle.resize(PhiAngleList.size());
9763  vector<vector<su2double> > NearFieldWeight_PhiAngle; NearFieldWeight_PhiAngle.resize(PhiAngleList.size());
9764  vector<vector<su2double> > Weight_PhiAngle; Weight_PhiAngle.resize(PhiAngleList.size());
9765 
9766  /*--- Distribute the values among the different PhiAngles ---*/
9767 
9768  for (iVertex = 0; iVertex < nVertex_NearField; iVertex++)
9769  for (iPhiAngle = 0; iPhiAngle < PhiAngleList.size(); iPhiAngle++)
9770  if (AzimuthalAngle[iVertex] == PhiAngleList[iPhiAngle]) {
9771  Xcoord_PhiAngle[iPhiAngle].push_back(Xcoord[iVertex]);
9772  Ycoord_PhiAngle[iPhiAngle].push_back(Ycoord[iVertex]);
9773  Zcoord_PhiAngle[iPhiAngle].push_back(Zcoord[iVertex]);
9774  IdPoint_PhiAngle[iPhiAngle].push_back(IdPoint[iVertex]);
9775  IdDomain_PhiAngle[iPhiAngle].push_back(IdDomain[iVertex]);
9776  Pressure_PhiAngle[iPhiAngle].push_back(Pressure[iVertex]);
9777  FaceArea_PhiAngle[iPhiAngle].push_back(FaceArea[iVertex]);
9778  EquivArea_PhiAngle[iPhiAngle].push_back(EquivArea[iVertex]);
9779  TargetArea_PhiAngle[iPhiAngle].push_back(TargetArea[iVertex]);
9780  NearFieldWeight_PhiAngle[iPhiAngle].push_back(NearFieldWeight[iVertex]);
9781  Weight_PhiAngle[iPhiAngle].push_back(Weight[iVertex]);
9782  }
9783 
9784  /*--- Order the arrays (x Coordinate, Pressure, Point, and Domain) ---*/
9785 
9786  for (iPhiAngle = 0; iPhiAngle < PhiAngleList.size(); iPhiAngle++)
9787  for (iVertex = 0; iVertex < Xcoord_PhiAngle[iPhiAngle].size(); iVertex++)
9788  for (jVertex = 0; jVertex < Xcoord_PhiAngle[iPhiAngle].size() - 1 - iVertex; jVertex++)
9789  if (Xcoord_PhiAngle[iPhiAngle][jVertex] > Xcoord_PhiAngle[iPhiAngle][jVertex+1]) {
9790  auxXCoord = Xcoord_PhiAngle[iPhiAngle][jVertex]; Xcoord_PhiAngle[iPhiAngle][jVertex] = Xcoord_PhiAngle[iPhiAngle][jVertex+1]; Xcoord_PhiAngle[iPhiAngle][jVertex+1] = auxXCoord;
9791  auxYCoord = Ycoord_PhiAngle[iPhiAngle][jVertex]; Ycoord_PhiAngle[iPhiAngle][jVertex] = Ycoord_PhiAngle[iPhiAngle][jVertex+1]; Ycoord_PhiAngle[iPhiAngle][jVertex+1] = auxYCoord;
9792  auxZCoord = Zcoord_PhiAngle[iPhiAngle][jVertex]; Zcoord_PhiAngle[iPhiAngle][jVertex] = Zcoord_PhiAngle[iPhiAngle][jVertex+1]; Zcoord_PhiAngle[iPhiAngle][jVertex+1] = auxZCoord;
9793  auxPress = Pressure_PhiAngle[iPhiAngle][jVertex]; Pressure_PhiAngle[iPhiAngle][jVertex] = Pressure_PhiAngle[iPhiAngle][jVertex+1]; Pressure_PhiAngle[iPhiAngle][jVertex+1] = auxPress;
9794  auxArea = FaceArea_PhiAngle[iPhiAngle][jVertex]; FaceArea_PhiAngle[iPhiAngle][jVertex] = FaceArea_PhiAngle[iPhiAngle][jVertex+1]; FaceArea_PhiAngle[iPhiAngle][jVertex+1] = auxArea;
9795  auxPoint = IdPoint_PhiAngle[iPhiAngle][jVertex]; IdPoint_PhiAngle[iPhiAngle][jVertex] = IdPoint_PhiAngle[iPhiAngle][jVertex+1]; IdPoint_PhiAngle[iPhiAngle][jVertex+1] = auxPoint;
9796  auxDomain = IdDomain_PhiAngle[iPhiAngle][jVertex]; IdDomain_PhiAngle[iPhiAngle][jVertex] = IdDomain_PhiAngle[iPhiAngle][jVertex+1]; IdDomain_PhiAngle[iPhiAngle][jVertex+1] = auxDomain;
9797  }
9798 
9799 
9800  /*--- Check that all the azimuth lists have the same size ---*/
9801 
9802  unsigned short nVertex = Xcoord_PhiAngle[0].size();
9803  for (iPhiAngle = 0; iPhiAngle < PhiAngleList.size(); iPhiAngle++) {
9804  unsigned short nVertex_aux = Xcoord_PhiAngle[iPhiAngle].size();
9805  if (nVertex_aux != nVertex) cout <<"Be careful!!! one azimuth list is shorter than the other"<< endl;
9806  nVertex = min(nVertex, nVertex_aux);
9807  }
9808 
9809  /*--- Compute equivalent area distribution at each azimuth angle ---*/
9810 
9811  for (iPhiAngle = 0; iPhiAngle < PhiAngleList.size(); iPhiAngle++) {
9812  EquivArea_PhiAngle[iPhiAngle][0] = 0.0;
9813  for (iVertex = 1; iVertex < EquivArea_PhiAngle[iPhiAngle].size(); iVertex++) {
9814  EquivArea_PhiAngle[iPhiAngle][iVertex] = 0.0;
9815 
9816  Coord_i = Xcoord_PhiAngle[iPhiAngle][iVertex]*cos(AoA) - Zcoord_PhiAngle[iPhiAngle][iVertex]*sin(AoA);
9817 
9818  for (jVertex = 0; jVertex < iVertex-1; jVertex++) {
9819 
9820  Coord_j = Xcoord_PhiAngle[iPhiAngle][jVertex]*cos(AoA) - Zcoord_PhiAngle[iPhiAngle][jVertex]*sin(AoA);
9821  jp1Coord = Xcoord_PhiAngle[iPhiAngle][jVertex+1]*cos(AoA) - Zcoord_PhiAngle[iPhiAngle][jVertex+1]*sin(AoA);
9822 
9823  jFunction = factor*(Pressure_PhiAngle[iPhiAngle][jVertex] - Pressure_Inf)*sqrt(Coord_i-Coord_j);
9824  jp1Function = factor*(Pressure_PhiAngle[iPhiAngle][jVertex+1] - Pressure_Inf)*sqrt(Coord_i-jp1Coord);
9825 
9826  DeltaX = (jp1Coord-Coord_j);
9827  MeanFuntion = 0.5*(jp1Function + jFunction);
9828  EquivArea_PhiAngle[iPhiAngle][iVertex] += DeltaX * MeanFuntion;
9829  }
9830  }
9831  }
9832 
9833  /*--- Create a file with the equivalent area distribution at each azimuthal angle ---*/
9834 
9835  NearFieldEA_file.precision(15);
9836 
9837  if (output) {
9838 
9839  NearFieldEA_file.open("Equivalent_Area.dat", ios::out);
9840  NearFieldEA_file << "TITLE = \"Equivalent Area evaluation at each azimuthal angle\"" << "\n";
9841 
9842  if (config->GetSystemMeasurements() == US)
9843  NearFieldEA_file << "VARIABLES = \"Height (in) at r="<< R_Plane*12.0 << " in. (cyl. coord. system)\"";
9844  else
9845  NearFieldEA_file << "VARIABLES = \"Height (m) at r="<< R_Plane << " m. (cylindrical coordinate system)\"";
9846 
9847  for (iPhiAngle = 0; iPhiAngle < PhiAngleList.size(); iPhiAngle++) {
9848  if (config->GetSystemMeasurements() == US)
9849  NearFieldEA_file << ", \"Equivalent Area (ft<sup>2</sup>), <greek>F</greek>= " << PhiAngleList[iPhiAngle] << " deg.\"";
9850  else
9851  NearFieldEA_file << ", \"Equivalent Area (m<sup>2</sup>), <greek>F</greek>= " << PhiAngleList[iPhiAngle] << " deg.\"";
9852  }
9853 
9854  NearFieldEA_file << "\n";
9855  for (iVertex = 0; iVertex < EquivArea_PhiAngle[0].size(); iVertex++) {
9856 
9857  su2double XcoordRot = Xcoord_PhiAngle[0][iVertex]*cos(AoA) - Zcoord_PhiAngle[0][iVertex]*sin(AoA);
9858  su2double XcoordRot_init = Xcoord_PhiAngle[0][0]*cos(AoA) - Zcoord_PhiAngle[0][0]*sin(AoA);
9859 
9860  if (config->GetSystemMeasurements() == US)
9861  NearFieldEA_file << scientific << (XcoordRot - XcoordRot_init) * 12.0;
9862  else
9863  NearFieldEA_file << scientific << (XcoordRot - XcoordRot_init);
9864 
9865  for (iPhiAngle = 0; iPhiAngle < PhiAngleList.size(); iPhiAngle++) {
9866  NearFieldEA_file << scientific << ", " << EquivArea_PhiAngle[iPhiAngle][iVertex];
9867  }
9868 
9869  NearFieldEA_file << "\n";
9870 
9871  }
9872  NearFieldEA_file.close();
9873 
9874  }
9875 
9876  /*--- Read target equivalent area from the configuration file,
9877  this first implementation requires a complete table (same as the original
9878  EA table). so... no interpolation. ---*/
9879 
9880  vector<vector<su2double> > TargetArea_PhiAngle_Trans;
9881  TargetEA_file.open("TargetEA.dat", ios::in);
9882 
9883  if (TargetEA_file.fail()) {
9884  /*--- Set the table to 0 ---*/
9885  for (iPhiAngle = 0; iPhiAngle < PhiAngleList.size(); iPhiAngle++)
9886  for (iVertex = 0; iVertex < TargetArea_PhiAngle[iPhiAngle].size(); iVertex++)
9887  TargetArea_PhiAngle[iPhiAngle][iVertex] = 0.0;
9888  }
9889  else {
9890 
9891  /*--- skip header lines ---*/
9892 
9893  string line;
9894  getline(TargetEA_file, line);
9895  getline(TargetEA_file, line);
9896 
9897  while (TargetEA_file) {
9898 
9899  string line;
9900  getline(TargetEA_file, line);
9901  istringstream is(line);
9902  vector<su2double> row;
9903  unsigned short iter = 0;
9904 
9905  while (is.good()) {
9906  string token;
9907  getline(is, token,',');
9908 
9909  istringstream js(token);
9910 
9911  su2double data;
9912  js >> data;
9913 
9914  /*--- The first element in the table is the coordinate (in or m)---*/
9915 
9916  if (iter != 0) row.push_back(data);
9917  iter++;
9918 
9919  }
9920  TargetArea_PhiAngle_Trans.push_back(row);
9921  }
9922 
9923  for (iPhiAngle = 0; iPhiAngle < PhiAngleList.size(); iPhiAngle++)
9924  for (iVertex = 0; iVertex < EquivArea_PhiAngle[iPhiAngle].size(); iVertex++)
9925  TargetArea_PhiAngle[iPhiAngle][iVertex] = TargetArea_PhiAngle_Trans[iVertex][iPhiAngle];
9926 
9927  }
9928 
9929  /*--- Divide by the number of Phi angles in the nearfield ---*/
9930 
9931  su2double PhiFactor = 1.0/su2double(PhiAngleList.size());
9932 
9933  /*--- Evaluate the objective function ---*/
9934 
9935  InverseDesign = 0;
9936  for (iPhiAngle = 0; iPhiAngle < PhiAngleList.size(); iPhiAngle++)
9937  for (iVertex = 0; iVertex < EquivArea_PhiAngle[iPhiAngle].size(); iVertex++) {
9938  Weight_PhiAngle[iPhiAngle][iVertex] = 1.0;
9939  Coord_i = Xcoord_PhiAngle[iPhiAngle][iVertex];
9940 
9941  su2double Difference = EquivArea_PhiAngle[iPhiAngle][iVertex]-TargetArea_PhiAngle[iPhiAngle][iVertex];
9942  su2double percentage = fabs(Difference)*100/fabs(TargetArea_PhiAngle[iPhiAngle][iVertex]);
9943 
9944  if ((percentage < 0.1) || (Coord_i < XCoordBegin_OF) || (Coord_i > XCoordEnd_OF)) Difference = 0.0;
9945 
9946  InverseDesign += EAScaleFactor*PhiFactor*Weight_PhiAngle[iPhiAngle][iVertex]*Difference*Difference;
9947 
9948  }
9949 
9950  /*--- Evaluate the weight of the nearfield pressure (adjoint input) ---*/
9951 
9952  for (iPhiAngle = 0; iPhiAngle < PhiAngleList.size(); iPhiAngle++)
9953  for (iVertex = 0; iVertex < EquivArea_PhiAngle[iPhiAngle].size(); iVertex++) {
9954  Coord_i = Xcoord_PhiAngle[iPhiAngle][iVertex];
9955  NearFieldWeight_PhiAngle[iPhiAngle][iVertex] = 0.0;
9956  for (jVertex = iVertex; jVertex < EquivArea_PhiAngle[iPhiAngle].size(); jVertex++) {
9957  Coord_j = Xcoord_PhiAngle[iPhiAngle][jVertex];
9958  Weight_PhiAngle[iPhiAngle][iVertex] = 1.0;
9959 
9960  su2double Difference = EquivArea_PhiAngle[iPhiAngle][jVertex]-TargetArea_PhiAngle[iPhiAngle][jVertex];
9961  su2double percentage = fabs(Difference)*100/fabs(TargetArea_PhiAngle[iPhiAngle][jVertex]);
9962 
9963  if ((percentage < 0.1) || (Coord_j < XCoordBegin_OF) || (Coord_j > XCoordEnd_OF)) Difference = 0.0;
9964 
9965  NearFieldWeight_PhiAngle[iPhiAngle][iVertex] += EAScaleFactor*PhiFactor*Weight_PhiAngle[iPhiAngle][iVertex]*2.0*Difference*factor*sqrt(Coord_j-Coord_i);
9966  }
9967  }
9968 
9969  /*--- Write the Nearfield pressure at each Azimuthal PhiAngle ---*/
9970 
9971  EquivArea_file.precision(15);
9972 
9973  if (output) {
9974 
9975  EquivArea_file.open("nearfield_flow.dat", ios::out);
9976  EquivArea_file << "TITLE = \"Equivalent Area evaluation at each azimuthal angle\"" << "\n";
9977 
9978  if (config->GetSystemMeasurements() == US)
9979  EquivArea_file << "VARIABLES = \"Height (in) at r="<< R_Plane*12.0 << " in. (cyl. coord. system)\",\"Equivalent Area (ft<sup>2</sup>)\",\"Target Equivalent Area (ft<sup>2</sup>)\",\"Cp\"" << "\n";
9980  else
9981  EquivArea_file << "VARIABLES = \"Height (m) at r="<< R_Plane << " m. (cylindrical coordinate system)\",\"Equivalent Area (m<sup>2</sup>)\",\"Target Equivalent Area (m<sup>2</sup>)\",\"Cp\"" << "\n";
9982 
9983  for (iPhiAngle = 0; iPhiAngle < PhiAngleList.size(); iPhiAngle++) {
9984  EquivArea_file << fixed << "ZONE T= \"<greek>F</greek>=" << PhiAngleList[iPhiAngle] << " deg.\"" << "\n";
9985  for (iVertex = 0; iVertex < Xcoord_PhiAngle[iPhiAngle].size(); iVertex++) {
9986 
9987  su2double XcoordRot = Xcoord_PhiAngle[0][iVertex]*cos(AoA) - Zcoord_PhiAngle[0][iVertex]*sin(AoA);
9988  su2double XcoordRot_init = Xcoord_PhiAngle[0][0]*cos(AoA) - Zcoord_PhiAngle[0][0]*sin(AoA);
9989 
9990  if (config->GetSystemMeasurements() == US)
9991  EquivArea_file << scientific << (XcoordRot - XcoordRot_init) * 12.0;
9992  else
9993  EquivArea_file << scientific << (XcoordRot - XcoordRot_init);
9994 
9995  EquivArea_file << scientific << ", " << EquivArea_PhiAngle[iPhiAngle][iVertex]
9996  << ", " << TargetArea_PhiAngle[iPhiAngle][iVertex] << ", " << (Pressure_PhiAngle[iPhiAngle][iVertex]-Pressure_Inf)/Pressure_Inf << "\n";
9997  }
9998  }
9999 
10000  EquivArea_file.close();
10001 
10002  }
10003 
10004  /*--- Write Weight file for adjoint computation ---*/
10005 
10006  FuncGrad_file.precision(15);
10007 
10008  if (output) {
10009 
10010  FuncGrad_file.open("WeightNF.dat", ios::out);
10011 
10012  FuncGrad_file << scientific << "-1.0";
10013  for (iPhiAngle = 0; iPhiAngle < PhiAngleList.size(); iPhiAngle++)
10014  FuncGrad_file << scientific << "\t" << PhiAngleList[iPhiAngle];
10015  FuncGrad_file << "\n";
10016 
10017  for (iVertex = 0; iVertex < NearFieldWeight_PhiAngle[0].size(); iVertex++) {
10018  su2double XcoordRot = Xcoord_PhiAngle[0][iVertex]*cos(AoA) - Zcoord_PhiAngle[0][iVertex]*sin(AoA);
10019  FuncGrad_file << scientific << XcoordRot;
10020  for (iPhiAngle = 0; iPhiAngle < PhiAngleList.size(); iPhiAngle++)
10021  FuncGrad_file << scientific << "\t" << NearFieldWeight_PhiAngle[iPhiAngle][iVertex];
10022  FuncGrad_file << "\n";
10023  }
10024  FuncGrad_file.close();
10025 
10026  }
10027 
10028  /*--- Delete structures ---*/
10029 
10030  delete [] Xcoord; delete [] Ycoord; delete [] Zcoord;
10031  delete [] AzimuthalAngle; delete [] IdPoint; delete [] IdDomain;
10032  delete [] Pressure; delete [] FaceArea;
10033  delete [] EquivArea; delete [] TargetArea;
10034  delete [] NearFieldWeight; delete [] Weight;
10035 
10036  }
10037 
10038 #ifndef HAVE_MPI
10039 
10040  /*--- Store the value of the NearField coefficient ---*/
10041 
10042  solver->SetTotal_CEquivArea(InverseDesign);
10043 
10044 #else
10045 
10046  /*--- Send the value of the NearField coefficient to all the processors ---*/
10047 
10048  SU2_MPI::Bcast(&InverseDesign, 1, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
10049 
10050  /*--- Store the value of the NearField coefficient ---*/
10051 
10052  solver->SetTotal_CEquivArea(InverseDesign);
10053 
10054 #endif
10055 
10056 }
10057 
10058 void COutputLegacy::SpecialOutput_Distortion(CSolver *solver, CGeometry *geometry, CConfig *config, bool output) {
10059 
10060  unsigned short iMarker, iDim, iMarker_Analyze;
10061  unsigned long iPoint, iVertex;
10062  su2double xCoord = 0.0, yCoord = 0.0, zCoord = 0.0, Area = 0.0, *Vector, TotalArea = 0.0;
10063  su2double xCoord_CG = 0.0, yCoord_CG = 0.0, zCoord_CG = 0.0, TipRadius, HubRadius, Distance = 0.0, Distance_Mirror = 0.0;
10064  su2double *r, MinDistance, xCoord_ = 0.0, yCoord_ = 0.0, zCoord_ = 0;
10065  unsigned short iStation, iAngle, nAngle;
10066  char cstr[200];
10067  su2double *** ProbeArray, dx = 0.0, dy = 0.0, dz = 0.0, dx_ = 0.0, dy_ = 0.0, dz_ = 0.0, UpVector[3], radians, RotatedVector[3];
10068  su2double Pressure, SoundSpeed, Velocity2, Mach, Gamma, TotalPressure, Mach_Inf, TotalPressure_Inf,
10069  Temperature, TotalTemperature, Pressure_Inf, Temperature_Inf, TotalTemperature_Inf, Velocity_Inf, Density;
10070  unsigned short nDim = geometry->GetnDim();
10071  unsigned short Theta, nStation;
10072  unsigned long nVertex_Surface, nLocalVertex_Surface, MaxLocalVertex_Surface;
10073  unsigned long Buffer_Send_nVertex[1], *Buffer_Recv_nVertex = NULL;
10074  unsigned long Total_Index;
10075  unsigned short Theta_DC60 = 60, nStation_DC60 = 5;
10076  su2double PT_Mean, Mach_Mean, q_Mean, PT, q, *PT_Sector, PT_Sector_Min, DC60, *PT_Station, *PT_Station_Min, *Mach_Station, *Mach_Station_Min, IDR, IDC, IDC_Mach;
10077 
10078 
10079  bool Engine_HalfModel = config->GetEngine_HalfModel();
10080  su2double SignFlip = 1.0;
10081  su2double Beta, Alpha;
10082  su2double Mach_ij, Mach_ip1j, Mach_im1j, Mach_ijp1, Mach_ijm1, Filtered_Mach;
10083  su2double Alpha_ij, Alpha_ip1j, Alpha_im1j, Alpha_ijp1, Alpha_ijm1, Filtered_Alpha;
10084  su2double Beta_ij, Beta_ip1j, Beta_im1j, Beta_ijp1, Beta_ijm1, Filtered_Beta;
10085  su2double a, b, c, d;
10086 
10087  int iProcessor, nProcessor;
10088  nProcessor = size;
10089 
10090 
10091  if (rank == MASTER_NODE && !config->GetDiscrete_Adjoint()) cout << endl << "Writing Surface Analysis file (surface_analysis.dat).";
10092 
10093  /*--- Open and rrite file name with extension if unsteady ---*/
10094 
10095  ofstream SurfFlow_file;
10096 
10097  if (output && (rank == MASTER_NODE)) {
10098 
10099  if ((config->GetTabular_FileFormat() == TAB_CSV)) strcpy (cstr, "surface_analysis.vtk");
10100  else strcpy (cstr, "surface_analysis.dat");
10101 
10102  SurfFlow_file.precision(15);
10103 
10104  SurfFlow_file.open(cstr, ios::out);
10105 
10106  if ((config->GetTabular_FileFormat() == TAB_CSV)) {
10107  SurfFlow_file << "# vtk DataFile Version 3.0" << endl;
10108  SurfFlow_file << "vtk output" << endl;
10109  SurfFlow_file << "ASCII" << endl;
10110  }
10111  else {
10112  SurfFlow_file <<"TITLE = \"Surface Analysis\"" <<endl;
10113  SurfFlow_file <<"VARIABLES = \"y(in)\", \"z(in)\", \"PT/PT<sub>inf</sub>\", \"TT/TT<sub>inf</sub>\", \"P/P<sub>inf</sub>\", \"T/T<sub>inf</sub>\", \"v<sub>x</sub>/v<sub>inf</sub>\", \"v<sub>y</sub>/v<sub>inf</sub>\", \"v<sub>z</sub>/v<sub>inf</sub>\", \"<greek>a</greek> (deg)\", \"<greek>b</greek> (deg)\", \"Mach\", \"Filtered <greek>a</greek> (deg)\", \"Filtered <greek>b</greek> (deg)\", \"Filtered Mach\"" << endl;
10114  }
10115 
10116  }
10117 
10118  /*--- Loop over all the markers to analyze ---*/
10119 
10120  for (iMarker_Analyze = 0; iMarker_Analyze < config->GetnMarker_Analyze(); iMarker_Analyze++) {
10121 
10122  string Analyze_TagBound = config->GetMarker_Analyze_TagBound(iMarker_Analyze);
10123 
10124  nVertex_Surface = 0; nLocalVertex_Surface = 0; MaxLocalVertex_Surface = 0;
10125 
10126  /*--- Find the max number of surface vertices among all
10127  partitions and set up buffers. The master node will handle the
10128  writing of the CSV file after gathering all of the data. ---*/
10129 
10130  nLocalVertex_Surface = 0;
10131  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
10132  string Marker_TagBound = config->GetMarker_All_TagBound(iMarker);
10133  if (Marker_TagBound == Analyze_TagBound) {
10134  for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
10135  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
10136  if (geometry->node[iPoint]->GetDomain()) nLocalVertex_Surface++;
10137  }
10138  }
10139  }
10140 
10141  /*--- Communicate the number of local vertices on each partition
10142  to the master node ---*/
10143 
10144  Buffer_Send_nVertex[0] = nLocalVertex_Surface;
10145  if (rank == MASTER_NODE) Buffer_Recv_nVertex = new unsigned long [nProcessor];
10146 
10147 #ifdef HAVE_MPI
10148  SU2_MPI::Allreduce(&nLocalVertex_Surface, &MaxLocalVertex_Surface, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
10149  SU2_MPI::Gather(&Buffer_Send_nVertex, 1, MPI_UNSIGNED_LONG, Buffer_Recv_nVertex, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
10150 #else
10151  MaxLocalVertex_Surface = nLocalVertex_Surface;
10152  Buffer_Recv_nVertex[MASTER_NODE] = Buffer_Send_nVertex[MASTER_NODE];
10153 #endif
10154 
10155  /*--- Send and Recv buffers ---*/
10156 
10157  su2double *Buffer_Send_Coord_x = NULL, *Buffer_Recv_Coord_x = NULL;
10158  Buffer_Send_Coord_x = new su2double [MaxLocalVertex_Surface];
10159 
10160  su2double *Buffer_Send_Coord_y = NULL, *Buffer_Recv_Coord_y = NULL;
10161  Buffer_Send_Coord_y = new su2double [MaxLocalVertex_Surface];
10162 
10163  su2double *Buffer_Send_Coord_z = NULL, *Buffer_Recv_Coord_z = NULL;
10164  if (nDim == 3) Buffer_Send_Coord_z = new su2double [MaxLocalVertex_Surface];
10165 
10166  su2double *Buffer_Send_PT = NULL, *Buffer_Recv_PT = NULL;
10167  Buffer_Send_PT = new su2double [MaxLocalVertex_Surface];
10168 
10169  su2double *Buffer_Send_TT = NULL, *Buffer_Recv_TT = NULL;
10170  Buffer_Send_TT = new su2double [MaxLocalVertex_Surface];
10171 
10172  su2double *Buffer_Send_P = NULL, *Buffer_Recv_P = NULL;
10173  Buffer_Send_P = new su2double [MaxLocalVertex_Surface];
10174 
10175  su2double *Buffer_Send_T = NULL, *Buffer_Recv_T = NULL;
10176  Buffer_Send_T = new su2double [MaxLocalVertex_Surface];
10177 
10178  su2double *Buffer_Send_Mach = NULL, *Buffer_Recv_Mach = NULL;
10179  Buffer_Send_Mach = new su2double [MaxLocalVertex_Surface];
10180 
10181  su2double *Buffer_Send_Vel_x = NULL, *Buffer_Recv_Vel_x = NULL;
10182  Buffer_Send_Vel_x = new su2double [MaxLocalVertex_Surface];
10183 
10184  su2double *Buffer_Send_Vel_y = NULL, *Buffer_Recv_Vel_y = NULL;
10185  Buffer_Send_Vel_y = new su2double [MaxLocalVertex_Surface];
10186 
10187  su2double *Buffer_Send_Vel_z = NULL, *Buffer_Recv_Vel_z = NULL;
10188  if (nDim == 3) Buffer_Send_Vel_z = new su2double [MaxLocalVertex_Surface];
10189 
10190  su2double *Buffer_Send_q = NULL, *Buffer_Recv_q = NULL;
10191  Buffer_Send_q = new su2double [MaxLocalVertex_Surface];
10192 
10193  su2double *Buffer_Send_Area = NULL, *Buffer_Recv_Area = NULL;
10194  Buffer_Send_Area = new su2double [MaxLocalVertex_Surface];
10195 
10196  /*--- Prepare the receive buffers on the master node only. ---*/
10197 
10198  if (rank == MASTER_NODE) {
10199  Buffer_Recv_Coord_x = new su2double [nProcessor*MaxLocalVertex_Surface];
10200  Buffer_Recv_Coord_y = new su2double [nProcessor*MaxLocalVertex_Surface];
10201  if (nDim == 3) Buffer_Recv_Coord_z = new su2double [nProcessor*MaxLocalVertex_Surface];
10202  Buffer_Recv_PT = new su2double [nProcessor*MaxLocalVertex_Surface];
10203  Buffer_Recv_TT = new su2double [nProcessor*MaxLocalVertex_Surface];
10204  Buffer_Recv_P = new su2double [nProcessor*MaxLocalVertex_Surface];
10205  Buffer_Recv_T = new su2double [nProcessor*MaxLocalVertex_Surface];
10206  Buffer_Recv_Mach = new su2double [nProcessor*MaxLocalVertex_Surface];
10207  Buffer_Recv_Vel_x = new su2double [nProcessor*MaxLocalVertex_Surface];
10208  Buffer_Recv_Vel_y = new su2double [nProcessor*MaxLocalVertex_Surface];
10209  if (nDim == 3) {
10210  Buffer_Recv_Vel_z = new su2double [nProcessor*MaxLocalVertex_Surface];
10211  }
10212  Buffer_Recv_q = new su2double [nProcessor*MaxLocalVertex_Surface];
10213  Buffer_Recv_Area = new su2double [nProcessor*MaxLocalVertex_Surface];
10214  }
10215 
10216  /*--- Loop over all vertices in this partition and load the
10217  data of the specified type into the buffer to be sent to
10218  the master node. ---*/
10219 
10220  nVertex_Surface = 0;
10221  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
10222  string Marker_TagBound = config->GetMarker_All_TagBound(iMarker);
10223  if (Marker_TagBound == Analyze_TagBound) {
10224 
10225  for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
10226  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
10227 
10228  if (geometry->node[iPoint]->GetDomain()) {
10229 
10230  Buffer_Send_Coord_x[nVertex_Surface] = geometry->node[iPoint]->GetCoord(0);
10231  Buffer_Send_Coord_y[nVertex_Surface] = geometry->node[iPoint]->GetCoord(1);
10232  if (nDim == 3) { Buffer_Send_Coord_z[nVertex_Surface] = geometry->node[iPoint]->GetCoord(2); }
10233 
10234  Pressure = solver->GetNodes()->GetPressure(iPoint);
10235  Density = solver->GetNodes()->GetDensity(iPoint);
10236  Temperature = solver->GetNodes()->GetTemperature(iPoint);
10237  SoundSpeed = solver->GetNodes()->GetSoundSpeed(iPoint);
10238  Velocity2 = solver->GetNodes()->GetVelocity2(iPoint);
10239  Mach = sqrt(Velocity2)/SoundSpeed;
10240  Gamma = config->GetGamma();
10241 
10242  Mach_Inf = config->GetMach();
10243  Pressure_Inf = config->GetPressure_FreeStreamND();
10244  Temperature_Inf = config->GetTemperature_FreeStreamND();
10245  Velocity_Inf = sqrt(config->GetVelocity_FreeStreamND()[0]*config->GetVelocity_FreeStreamND()[0]
10246  + config->GetVelocity_FreeStreamND()[1]*config->GetVelocity_FreeStreamND()[1]
10247  + config->GetVelocity_FreeStreamND()[2]*config->GetVelocity_FreeStreamND()[2]);
10248 
10249  Buffer_Send_P[nVertex_Surface] = Pressure / Pressure_Inf;
10250  Buffer_Send_T[nVertex_Surface] = Temperature / Temperature_Inf;
10251  Buffer_Send_Mach[nVertex_Surface] = Mach;
10252 
10253  TotalPressure = Pressure * pow( 1.0 + Mach * Mach * 0.5 * (Gamma - 1.0), Gamma / (Gamma - 1.0));
10254  TotalPressure_Inf = Pressure_Inf * pow( 1.0 + Mach_Inf * Mach_Inf * 0.5 * (Gamma - 1.0), Gamma / (Gamma - 1.0));
10255  Buffer_Send_PT[nVertex_Surface] = TotalPressure / TotalPressure_Inf;
10256 
10257  TotalTemperature = Temperature * (1.0 + Mach * Mach * 0.5 * (Gamma - 1.0));
10258  TotalTemperature_Inf = Temperature_Inf * (1.0 + Mach * Mach * 0.5 * (Gamma - 1.0));
10259  Buffer_Send_TT[nVertex_Surface] = TotalTemperature / TotalTemperature_Inf;
10260 
10261  Buffer_Send_Vel_x[nVertex_Surface] = solver->GetNodes()->GetVelocity(iPoint,0) / Velocity_Inf;
10262  Buffer_Send_Vel_y[nVertex_Surface] = solver->GetNodes()->GetVelocity(iPoint,1) / Velocity_Inf;
10263  if (nDim == 3) {
10264  Buffer_Send_Vel_z[nVertex_Surface] = solver->GetNodes()->GetVelocity(iPoint,2) / Velocity_Inf;
10265  }
10266 
10267  Buffer_Send_q[nVertex_Surface] = 0.5*Density*Velocity2;
10268 
10269  Vector = geometry->vertex[iMarker][iVertex]->GetNormal();
10270  Area = 0.0; for (iDim = 0; iDim < nDim; iDim++) { Area += Vector[iDim]*Vector[iDim]; } Area = sqrt(Area);
10271  Buffer_Send_Area[nVertex_Surface] = Area;
10272 
10273  /*--- If US system, the output should be in inches ---*/
10274 
10275  if (config->GetSystemMeasurements() == US) {
10276 
10277  Buffer_Send_Coord_x[nVertex_Surface] *= 12.0;
10278  Buffer_Send_Coord_y[nVertex_Surface] *= 12.0;
10279  if (nDim == 3) Buffer_Send_Coord_z[nVertex_Surface] *= 12.0;
10280  Buffer_Send_Area[nVertex_Surface] *= 144.0;
10281 
10282  }
10283 
10284  nVertex_Surface++;
10285 
10286  }
10287  }
10288  break;
10289  }
10290  }
10291 
10292  /*--- Send the information to the master node ---*/
10293 
10294 #ifdef HAVE_MPI
10295 
10296  SU2_MPI::Gather(Buffer_Send_Coord_x, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_Coord_x, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
10297  SU2_MPI::Gather(Buffer_Send_Coord_y, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_Coord_y, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
10298  if (nDim == 3) SU2_MPI::Gather(Buffer_Send_Coord_z, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_Coord_z, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
10299  SU2_MPI::Gather(Buffer_Send_PT, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_PT, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
10300  SU2_MPI::Gather(Buffer_Send_TT, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_TT, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
10301  SU2_MPI::Gather(Buffer_Send_P, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_P, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
10302  SU2_MPI::Gather(Buffer_Send_T, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_T, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
10303  SU2_MPI::Gather(Buffer_Send_Mach, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_Mach, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
10304  SU2_MPI::Gather(Buffer_Send_Vel_x, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_Vel_x, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
10305  SU2_MPI::Gather(Buffer_Send_Vel_y, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_Vel_y, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
10306  if (nDim == 3) SU2_MPI::Gather(Buffer_Send_Vel_z, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_Vel_z, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
10307  SU2_MPI::Gather(Buffer_Send_q, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_q, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
10308  SU2_MPI::Gather(Buffer_Send_Area, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_Area, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
10309 
10310 #else
10311 
10312  for (iVertex = 0; iVertex < MaxLocalVertex_Surface; iVertex++) {
10313  Buffer_Recv_Coord_x[iVertex] = Buffer_Send_Coord_x[iVertex];
10314  Buffer_Recv_Coord_y[iVertex] = Buffer_Send_Coord_y[iVertex];
10315  if (nDim == 3) Buffer_Recv_Coord_z[iVertex] = Buffer_Send_Coord_z[iVertex];
10316  Buffer_Recv_PT[iVertex] = Buffer_Send_PT[iVertex];
10317  Buffer_Recv_TT[iVertex] = Buffer_Send_TT[iVertex];
10318  Buffer_Recv_P[iVertex] = Buffer_Send_P[iVertex];
10319  Buffer_Recv_T[iVertex] = Buffer_Send_T[iVertex];
10320  Buffer_Recv_Mach[iVertex] = Buffer_Send_Mach[iVertex];
10321  Buffer_Recv_Vel_x[iVertex] = Buffer_Send_Vel_x[iVertex];
10322  Buffer_Recv_Vel_y[iVertex] = Buffer_Send_Vel_y[iVertex];
10323  if (nDim == 3) Buffer_Recv_Vel_z[iVertex] = Buffer_Send_Vel_z[iVertex];
10324  Buffer_Recv_q[iVertex] = Buffer_Send_q[iVertex];
10325  Buffer_Recv_Area[iVertex] = Buffer_Send_Area[iVertex];
10326  }
10327 
10328 #endif
10329 
10330  if (rank == MASTER_NODE) {
10331 
10332  /*--- Compute the location of the critical points of the distortion measure, and center of gravity ---*/
10333 
10334  TotalArea = 0.0; xCoord_CG = 0.0; yCoord_CG = 0.0; zCoord_CG = 0.0; PT_Mean = 0.0; Mach_Mean = 0.0; q_Mean = 0.0;
10335 
10336  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
10337  for (iVertex = 0; iVertex < Buffer_Recv_nVertex[iProcessor]; iVertex++) {
10338 
10339  /*--- Current index position and global index ---*/
10340 
10341  Total_Index = iProcessor*MaxLocalVertex_Surface+iVertex;
10342 
10343  /*--- Retrieve the merged data for this node ---*/
10344 
10345  xCoord = Buffer_Recv_Coord_x[Total_Index];
10346  yCoord = Buffer_Recv_Coord_y[Total_Index];
10347  if (nDim == 3) zCoord = Buffer_Recv_Coord_z[Total_Index];
10348  PT = Buffer_Recv_PT[Total_Index];
10349  Mach = Buffer_Recv_Mach[Total_Index];
10350  q = Buffer_Recv_q[Total_Index];
10351 
10352  Area = Buffer_Recv_Area[Total_Index];
10353  TotalArea += Area;
10354  xCoord_CG += xCoord*Area;
10355  yCoord_CG += yCoord*Area;
10356  zCoord_CG += zCoord*Area;
10357  PT_Mean += PT*Area;
10358  Mach_Mean += PT*Area;
10359  q_Mean += q*Area;
10360 
10361  }
10362  }
10363 
10364  /*--- Evaluate the area averaged pressure and CG ---*/
10365 
10366  xCoord_CG = xCoord_CG / TotalArea;
10367  yCoord_CG = yCoord_CG / TotalArea;
10368  zCoord_CG = zCoord_CG / TotalArea;
10369  PT_Mean /= TotalArea;
10370  Mach_Mean /= TotalArea;
10371  q_Mean /= TotalArea;
10372 
10373  /*--- If it is a half model, CGy = 0 ---*/
10374 
10375  if (Engine_HalfModel) { yCoord_CG = 0.0; }
10376 
10377  /*--- Compute hub and tip radius ---*/
10378 
10379  TipRadius = 1E-6; HubRadius = 1E6;
10380  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
10381  for (iVertex = 0; iVertex < Buffer_Recv_nVertex[iProcessor]; iVertex++) {
10382 
10383  /*--- Current index position and global index ---*/
10384 
10385  Total_Index = iProcessor*MaxLocalVertex_Surface+iVertex;
10386 
10387  /*--- Retrieve the merged data for this node ---*/
10388 
10389  xCoord = Buffer_Recv_Coord_x[Total_Index];
10390  yCoord = Buffer_Recv_Coord_y[Total_Index];
10391  if (nDim == 3) zCoord = Buffer_Recv_Coord_z[Total_Index];
10392 
10393  if (nDim == 2)
10394  Distance = sqrt((xCoord_CG-xCoord)*(xCoord_CG-xCoord) +
10395  (yCoord_CG-yCoord)*(yCoord_CG-yCoord));
10396 
10397  if (nDim == 3)
10398  Distance = sqrt((xCoord_CG-xCoord)*(xCoord_CG-xCoord) +
10399  (yCoord_CG-yCoord)*(yCoord_CG-yCoord) +
10400  (zCoord_CG-zCoord)*(zCoord_CG-zCoord));
10401 
10402  if (Distance > TipRadius) TipRadius = Distance;
10403  if (Distance < HubRadius) HubRadius = Distance;
10404 
10405  }
10406  }
10407 
10408  if (HubRadius/TipRadius < 0.05) HubRadius = 0.0;
10409 
10410  /*--- Evaluate the DC60 parameter ---*/
10411 
10412  Theta = Theta_DC60;
10413  nStation = nStation_DC60;
10414 
10415  nAngle = SU2_TYPE::Int(360/float(Theta));
10416  r = new su2double [nStation+1];
10417 
10418  /*--- Allocate memory ---*/
10419 
10420  PT_Sector = new su2double [nAngle];
10421  ProbeArray = new su2double ** [nAngle];
10422  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10423  ProbeArray[iAngle] = new su2double * [nStation];
10424  for (iStation = 0; iStation < nStation; iStation++) {
10425  ProbeArray[iAngle][iStation] = new su2double [5];
10426  }
10427  }
10428 
10429  /*--- Define the radius for each probe ---*/
10430 
10431  r[0] = HubRadius; r[nStation] = TipRadius;
10432  for (iStation = 1; iStation < nStation; iStation++) {
10433  r[iStation] = sqrt( r[iStation-1]*r[iStation-1] + (r[nStation]*r[nStation] - r[0]*r[0])/float(nStation) );
10434  }
10435 
10436  /*--- Define the probe rack ---*/
10437 
10438  UpVector[0] = 0.0; UpVector[1] = 0.0; UpVector[2] = 1.0;
10439 
10440  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10441 
10442  radians = -iAngle*Theta*2.0*PI_NUMBER/360;
10443  RotatedVector[0] = UpVector[0];
10444  RotatedVector[1] = UpVector[1] * cos(radians) - UpVector[2] * sin(radians);
10445  RotatedVector[2] = UpVector[1] * sin(radians) + UpVector[2] * cos(radians);
10446 
10447  for (iStation = 1; iStation <= nStation; iStation++) {
10448  ProbeArray[iAngle][iStation-1][0] = xCoord_CG+RotatedVector[0]*sqrt(0.5*(r[iStation]*r[iStation]+r[iStation-1]*r[iStation-1]));
10449  ProbeArray[iAngle][iStation-1][1] = yCoord_CG+RotatedVector[1]*sqrt(0.5*(r[iStation]*r[iStation]+r[iStation-1]*r[iStation-1]));
10450  ProbeArray[iAngle][iStation-1][2] = zCoord_CG+RotatedVector[2]*sqrt(0.5*(r[iStation]*r[iStation]+r[iStation-1]*r[iStation-1]));
10451  }
10452 
10453  }
10454 
10455  /*--- Compute the Total pressure at each probe, closes grid point to the location ---*/
10456 
10457  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10458 
10459  for (iStation = 0; iStation < nStation; iStation++) {
10460  xCoord_ = ProbeArray[iAngle][iStation][0];
10461  yCoord_ = ProbeArray[iAngle][iStation][1];
10462  zCoord_ = ProbeArray[iAngle][iStation][2];
10463 
10464  MinDistance = 1E6;
10465 
10466  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
10467  for (iVertex = 0; iVertex < Buffer_Recv_nVertex[iProcessor]; iVertex++) {
10468 
10469  Total_Index = iProcessor*MaxLocalVertex_Surface+iVertex;
10470  xCoord = Buffer_Recv_Coord_x[Total_Index];
10471  yCoord = Buffer_Recv_Coord_y[Total_Index];
10472  if (nDim == 3) zCoord = Buffer_Recv_Coord_z[Total_Index];
10473 
10474  dx = (xCoord_ - xCoord); dy = (yCoord_ - yCoord);
10475  if (nDim == 3) dz = (zCoord_ - zCoord);
10476 
10477  Distance = dx*dx + dy*dy; if (nDim == 3) Distance += dz*dz; Distance = sqrt(Distance);
10478 
10479  if (Engine_HalfModel) {
10480 
10481  yCoord = -yCoord;
10482 
10483  dx_ = (xCoord_ - xCoord); dy_ = (yCoord_ - yCoord);
10484  if (nDim == 3) dz_ = (zCoord_ - zCoord);
10485 
10486  Distance_Mirror = dx_*dx_ + dy_*dy_;
10487  if (nDim == 3) Distance_Mirror += dz_*dz_;
10488  Distance_Mirror = sqrt(Distance_Mirror);
10489 
10490  if (Distance_Mirror < Distance) {
10491  Distance = Distance_Mirror;
10492  dx = dx_; dy = dy_;
10493  if (nDim == 3) dz = dz_;
10494  }
10495 
10496  }
10497 
10498  if (Distance <= MinDistance) {
10499  MinDistance = Distance;
10500  ProbeArray[iAngle][iStation][3] = Buffer_Recv_PT[Total_Index];
10501  ProbeArray[iAngle][iStation][4] = Buffer_Recv_q[Total_Index];
10502  }
10503 
10504  }
10505  }
10506 
10507  }
10508 
10509  }
10510 
10511  /*--- Evaluate the average pressure at each sector, fan face and dynamic pressure ---*/
10512 
10513  PT_Mean = 0.0; q_Mean = 0.0;
10514  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10515  PT_Sector[iAngle] = 0.0;
10516  for (iStation = 0; iStation < nStation; iStation++) {
10517  PT_Sector[iAngle] += ProbeArray[iAngle][iStation][3]/float(nStation);
10518  PT_Mean += ProbeArray[iAngle][iStation][3]/float(nStation*nAngle);
10519  q_Mean += ProbeArray[iAngle][iStation][4]/float(nStation*nAngle);
10520  }
10521  }
10522 
10523  /*--- Compute the min value of the averaged pressure at each sector ---*/
10524 
10525  PT_Sector_Min = PT_Sector[0];
10526  for (iAngle = 1; iAngle < nAngle; iAngle++) {
10527  if (PT_Sector[iAngle] <= PT_Sector_Min) PT_Sector_Min = PT_Sector[iAngle];
10528  }
10529 
10530  /*--- Set the value of the distortion, it only works for one surface ---*/
10531 
10532  Mach_Inf = config->GetMach();
10533  Gamma = config->GetGamma();
10534  TotalPressure_Inf = config->GetPressure_FreeStreamND() * pow( 1.0 + Mach_Inf * Mach_Inf *
10535  0.5 * (Gamma - 1.0), Gamma / (Gamma - 1.0));
10536 
10537  if (q_Mean != 0.0) DC60 = ((PT_Mean - PT_Sector_Min)*TotalPressure_Inf)/q_Mean;
10538  else DC60 = 0.0;
10539 
10540  config->SetSurface_DC60(iMarker_Analyze, DC60);
10541 
10542  solver->SetTotal_DC60(DC60);
10543 
10544  /*--- Deallocate the memory ---*/
10545 
10546  delete[] r;
10547 
10548  delete [] PT_Sector;
10549 
10550  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10551  for (iStation = 0; iStation < nStation; iStation++) {
10552  delete[] ProbeArray[iAngle][iStation];
10553  }
10554  }
10555  delete[] ProbeArray;
10556 
10557 
10558  /*--- Evaluate the IDC, and IDR parameters ---*/
10559 
10560  nStation = SU2_TYPE::Int(config->GetDistortionRack()[0]);
10561  Theta = SU2_TYPE::Int(config->GetDistortionRack()[1]);
10562  nAngle = SU2_TYPE::Int(360/float(Theta));
10563 
10564  /*--- Allocate memory ---*/
10565 
10566  r = new su2double [nStation+1];
10567  ProbeArray = new su2double ** [nAngle];
10568  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10569  ProbeArray[iAngle] = new su2double * [nStation];
10570  for (iStation = 0; iStation < nStation; iStation++) {
10571  ProbeArray[iAngle][iStation] = new su2double [4];
10572  }
10573  }
10574 
10575  /*--- Define the radius for each probe ---*/
10576 
10577  r[0] = HubRadius; r[nStation] = TipRadius;
10578  for (iStation = 1; iStation < nStation; iStation++) {
10579  r[iStation] = sqrt( r[iStation-1]*r[iStation-1] + (r[nStation]*r[nStation] - r[0]*r[0])/float(nStation) );
10580  }
10581 
10582  /*--- Define the probe rack ---*/
10583 
10584  UpVector[0] = 0.0; UpVector[1] = 0.0; UpVector[2] = 1.0;
10585 
10586  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10587 
10588  radians = -iAngle*Theta*2.0*PI_NUMBER/360;
10589  RotatedVector[0] = UpVector[0];
10590  RotatedVector[1] = UpVector[1] * cos(radians) - UpVector[2] * sin(radians);
10591  RotatedVector[2] = UpVector[1] * sin(radians) + UpVector[2] * cos(radians);
10592 
10593  for (iStation = 1; iStation <= nStation; iStation++) {
10594  ProbeArray[iAngle][iStation-1][0] = xCoord_CG+RotatedVector[0]*sqrt(0.5*(r[iStation]*r[iStation]+r[iStation-1]*r[iStation-1]));
10595  ProbeArray[iAngle][iStation-1][1] = yCoord_CG+RotatedVector[1]*sqrt(0.5*(r[iStation]*r[iStation]+r[iStation-1]*r[iStation-1]));
10596  ProbeArray[iAngle][iStation-1][2] = zCoord_CG+RotatedVector[2]*sqrt(0.5*(r[iStation]*r[iStation]+r[iStation-1]*r[iStation-1]));
10597  }
10598 
10599  }
10600 
10601  /*--- Compute the Total pressure at each probe, closes grid point to the location ---*/
10602 
10603  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10604  for (iStation = 0; iStation < nStation; iStation++) {
10605  xCoord_ = ProbeArray[iAngle][iStation][0];
10606  yCoord_ = ProbeArray[iAngle][iStation][1];
10607  zCoord_ = ProbeArray[iAngle][iStation][2];
10608 
10609  MinDistance = 1E6;
10610 
10611  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
10612  for (iVertex = 0; iVertex < Buffer_Recv_nVertex[iProcessor]; iVertex++) {
10613 
10614  Total_Index = iProcessor*MaxLocalVertex_Surface+iVertex;
10615  xCoord = Buffer_Recv_Coord_x[Total_Index];
10616  yCoord = Buffer_Recv_Coord_y[Total_Index];
10617  if (nDim == 3) zCoord = Buffer_Recv_Coord_z[Total_Index];
10618 
10619  dx = (xCoord_ - xCoord); dy = (yCoord_ - yCoord);
10620  if (nDim == 3) dz = (zCoord_ - zCoord);
10621 
10622  Distance = dx*dx + dy*dy; if (nDim == 3) Distance += dz*dz; Distance = sqrt(Distance);
10623 
10624  if (Engine_HalfModel) {
10625 
10626  yCoord = -yCoord;
10627 
10628  dx_ = (xCoord_ - xCoord); dy_ = (yCoord_ - yCoord);
10629  if (nDim == 3) dz_ = (zCoord_ - zCoord);
10630 
10631  Distance_Mirror = dx_*dx_ + dy_*dy_;
10632  if (nDim == 3) Distance_Mirror += dz_*dz_;
10633  Distance_Mirror = sqrt(Distance_Mirror);
10634 
10635  if (Distance_Mirror < Distance) {
10636  Distance = Distance_Mirror;
10637  dx = dx_; dy = dy_;
10638  if (nDim == 3) dz = dz_;
10639  }
10640 
10641  }
10642 
10643  if (Distance <= MinDistance) {
10644  MinDistance = Distance;
10645  ProbeArray[iAngle][iStation][3] = Buffer_Recv_PT[Total_Index];
10646  }
10647 
10648  }
10649  }
10650 
10651  }
10652 
10653  }
10654 
10655  /*--- Evaluate the average and min. pressure at each station/radius and fan ---*/
10656 
10657  PT_Station = new su2double [nStation];
10658  PT_Station_Min = new su2double [nStation];
10659 
10660  PT_Mean = 0.0;
10661  for (iStation = 0; iStation < nStation; iStation++) {
10662  PT_Station[iStation] = 0.0;
10663  PT_Station_Min[iStation] = ProbeArray[0][iStation][3];
10664  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10665  PT = ProbeArray[iAngle][iStation][3];
10666  PT_Station[iStation] += PT / float(nAngle);
10667  if (PT <= PT_Station_Min[iStation] ) PT_Station_Min[iStation] = PT;
10668  PT_Mean += ProbeArray[iAngle][iStation][3]/float(nStation*nAngle);
10669  }
10670  }
10671 
10672  /*--- Set the value of the distortion, it only works for one surface ---*/
10673 
10674  IDC = 0.0;
10675  for (iStation = 0; iStation < nStation-1; iStation++) {
10676  IDC = max (IDC, 0.5*((PT_Station[iStation] - PT_Station_Min[iStation])/PT_Mean
10677  + (PT_Station[iStation+1] - PT_Station_Min[iStation+1])/PT_Mean) );
10678 
10679  }
10680 
10681  config->SetSurface_IDC(iMarker_Analyze, IDC);
10682  solver->SetTotal_IDC(IDC);
10683 
10684  IDR = 0.0;
10685  for (iStation = 0; iStation < nStation; iStation++) {
10686  IDR = max (IDR, (PT_Mean-PT_Station[iStation])/PT_Mean);
10687  }
10688 
10689  config->SetSurface_IDR(iMarker_Analyze, IDR);
10690 
10691  solver->SetTotal_IDR(IDR);
10692 
10693  /*--- Release IDX parameters ---*/
10694 
10695  delete [] PT_Station_Min;
10696  delete [] PT_Station;
10697 
10698  /*--- Evaluate the IDC Mach parameter ---*/
10699 
10700  /*--- Compute the Mach number at each probe, closes grid point to the location ---*/
10701 
10702  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10703  for (iStation = 0; iStation < nStation; iStation++) {
10704  xCoord_ = ProbeArray[iAngle][iStation][0];
10705  yCoord_ = ProbeArray[iAngle][iStation][1];
10706  zCoord_ = ProbeArray[iAngle][iStation][2];
10707 
10708  MinDistance = 1E6;
10709 
10710  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
10711  for (iVertex = 0; iVertex < Buffer_Recv_nVertex[iProcessor]; iVertex++) {
10712 
10713  Total_Index = iProcessor*MaxLocalVertex_Surface+iVertex;
10714 
10715  xCoord = Buffer_Recv_Coord_x[Total_Index];
10716  yCoord = Buffer_Recv_Coord_y[Total_Index];
10717  if (nDim == 3) zCoord = Buffer_Recv_Coord_z[Total_Index];
10718 
10719  dx = (xCoord_ - xCoord); dy = (yCoord_ - yCoord);
10720  if (nDim == 3) dz = (zCoord_ - zCoord);
10721 
10722  Distance = dx*dx + dy*dy;
10723  if (nDim == 3) Distance += dz*dz;
10724  Distance = sqrt(Distance);
10725 
10726  if (Engine_HalfModel) {
10727 
10728  yCoord = -yCoord;
10729 
10730  dx_ = (xCoord_ - xCoord); dy_ = (yCoord_ - yCoord);
10731  if (nDim == 3) dz_ = (zCoord_ - zCoord);
10732 
10733  Distance_Mirror = dx_*dx_ + dy_*dy_;
10734  if (nDim == 3) Distance_Mirror += dz_*dz_;
10735  Distance_Mirror = sqrt(Distance_Mirror);
10736 
10737  if (Distance_Mirror < Distance) {
10738  Distance = Distance_Mirror;
10739  dx = dx_; dy = dy_;
10740  if (nDim == 3) dz = dz_;
10741  }
10742 
10743  }
10744 
10745  if (Distance <= MinDistance) {
10746  MinDistance = Distance;
10747  ProbeArray[iAngle][iStation][3] = Buffer_Recv_Mach[Total_Index];
10748  }
10749 
10750  }
10751  }
10752 
10753  }
10754 
10755  }
10756 
10757  /*--- Evaluate the average and min. pressure at each station/radius and fan face ---*/
10758 
10759  Mach_Station = new su2double [nStation];
10760  Mach_Station_Min = new su2double [nStation];
10761 
10762  Mach_Mean = 0.0;
10763  for (iStation = 0; iStation < nStation; iStation++) {
10764  Mach_Station[iStation] = 0.0;
10765  Mach_Station_Min[iStation] = ProbeArray[0][iStation][3];
10766  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10767  Mach = ProbeArray[iAngle][iStation][3];
10768  Mach_Station[iStation] += Mach / float(nAngle);
10769  if (Mach <= Mach_Station_Min[iStation] ) Mach_Station_Min[iStation] = Mach;
10770  Mach_Mean += ProbeArray[iAngle][iStation][3]/float(nStation*nAngle);
10771  }
10772  }
10773 
10774  /*--- Set the value of the distortion, it only works for one surface ---*/
10775 
10776  IDC_Mach = 0.0;
10777  for (iStation = 0; iStation < nStation-1; iStation++) {
10778  if (Mach_Mean != 0)
10779  IDC_Mach = max (IDC_Mach, 0.5*((Mach_Station[iStation] - Mach_Station_Min[iStation])/Mach_Mean
10780  + (Mach_Station[iStation+1] - Mach_Station_Min[iStation+1])/Mach_Mean) );
10781 
10782  }
10783 
10784  config->SetSurface_IDC_Mach(iMarker_Analyze, IDC_Mach);
10785 
10786  solver->SetTotal_IDC_Mach(IDC_Mach);
10787 
10788  delete [] Mach_Station_Min;
10789  delete [] Mach_Station;
10790 
10791  /*--- Release distortion parameters ---*/
10792 
10793  delete[] r;
10794  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10795  for (iStation = 0; iStation < nStation; iStation++) {
10796  delete[] ProbeArray[iAngle][iStation];
10797  }
10798  }
10799  delete[] ProbeArray;
10800 
10801  /*--- Create the distortion plot ---*/
10802 
10803  Theta = 10; nStation = 20;
10804 
10805  nAngle = SU2_TYPE::Int(360/float(Theta));
10806  r = new su2double [nStation+1];
10807 
10808  /*--- Allocate memory ---*/
10809 
10810  ProbeArray = new su2double ** [nAngle];
10811  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10812  ProbeArray[iAngle] = new su2double * [nStation];
10813  for (iStation = 0; iStation < nStation; iStation++) {
10814  ProbeArray[iAngle][iStation] = new su2double [11];
10815  }
10816  }
10817 
10818  /*--- Define the radius for each probe ---*/
10819 
10820  r[0] = HubRadius;
10821  r[nStation] = TipRadius;
10822 
10823  for (iStation = 1; iStation < nStation; iStation++) {
10824  r[iStation] = sqrt( r[iStation-1]*r[iStation-1] + (r[nStation]*r[nStation] - r[0]*r[0])/float(nStation) );
10825  }
10826 
10827  /*--- Define the probe rack ---*/
10828 
10829  UpVector[0] = 0.0; UpVector[1] = 0.0; UpVector[2] = 1.0;
10830 
10831  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10832 
10833  radians = -iAngle*Theta*2.0*PI_NUMBER/360;
10834  RotatedVector[0] = UpVector[0];
10835  RotatedVector[1] = UpVector[1] * cos(radians) - UpVector[2] * sin(radians);
10836  RotatedVector[2] = UpVector[1] * sin(radians) + UpVector[2] * cos(radians);
10837 
10838  for (iStation = 1; iStation <= nStation; iStation++) {
10839  ProbeArray[iAngle][iStation-1][0] = xCoord_CG+RotatedVector[0]*sqrt(0.5*(r[iStation]*r[iStation]+r[iStation-1]*r[iStation-1]));
10840  ProbeArray[iAngle][iStation-1][1] = yCoord_CG+RotatedVector[1]*sqrt(0.5*(r[iStation]*r[iStation]+r[iStation-1]*r[iStation-1]));
10841  ProbeArray[iAngle][iStation-1][2] = zCoord_CG+RotatedVector[2]*sqrt(0.5*(r[iStation]*r[iStation]+r[iStation-1]*r[iStation-1]));
10842  }
10843 
10844  }
10845 
10846  /*--- Compute the primitieve variables, closest grid point to the location + gradient ---*/
10847 
10848  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10849  for (iStation = 0; iStation < nStation; iStation++) {
10850  xCoord_ = ProbeArray[iAngle][iStation][0];
10851  yCoord_ = ProbeArray[iAngle][iStation][1];
10852  zCoord_ = ProbeArray[iAngle][iStation][2];
10853 
10854  MinDistance = 1E6;
10855 
10856  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
10857  for (iVertex = 0; iVertex < Buffer_Recv_nVertex[iProcessor]; iVertex++) {
10858 
10859  Total_Index = iProcessor*MaxLocalVertex_Surface+iVertex;
10860  xCoord = Buffer_Recv_Coord_x[Total_Index];
10861  yCoord = Buffer_Recv_Coord_y[Total_Index];
10862  if (nDim == 3) zCoord = Buffer_Recv_Coord_z[Total_Index];
10863 
10864  dx = (xCoord_ - xCoord); dy = (yCoord_ - yCoord);
10865  if (nDim == 3) dz = (zCoord_ - zCoord);
10866 
10867  Distance = dx*dx + dy*dy; if (nDim == 3) Distance += dz*dz; Distance = sqrt(Distance);
10868 
10869  SignFlip = 1.0;
10870 
10871  if (Engine_HalfModel) {
10872 
10873  yCoord = -yCoord;
10874 
10875  dx_ = (xCoord_ - xCoord);
10876  dy_ = (yCoord_ - yCoord);
10877  if (nDim == 3) dz_ = (zCoord_ - zCoord);
10878 
10879  Distance_Mirror = dx_*dx_ + dy_*dy_;
10880  if (nDim == 3) Distance_Mirror += dz_*dz_;
10881  Distance_Mirror = sqrt(Distance_Mirror);
10882 
10883  if (Distance_Mirror < Distance) {
10884  SignFlip = -1.0;
10885  Distance = Distance_Mirror;
10886  dx = dx_; dy = dy_;
10887  if (nDim == 3) dz = dz_;
10888  }
10889 
10890  }
10891 
10892 
10893  if (Distance <= MinDistance) {
10894  MinDistance = Distance;
10895  ProbeArray[iAngle][iStation][3] = Buffer_Recv_PT[Total_Index];
10896  ProbeArray[iAngle][iStation][4] = Buffer_Recv_TT[Total_Index];
10897  ProbeArray[iAngle][iStation][5] = Buffer_Recv_P[Total_Index];
10898  ProbeArray[iAngle][iStation][6] = Buffer_Recv_T[Total_Index];
10899  ProbeArray[iAngle][iStation][7] = Buffer_Recv_Mach[Total_Index];
10900  ProbeArray[iAngle][iStation][8] = Buffer_Recv_Vel_x[Total_Index];
10901  ProbeArray[iAngle][iStation][9] = SignFlip * Buffer_Recv_Vel_y[Total_Index];
10902  if (nDim == 3) ProbeArray[iAngle][iStation][10] = Buffer_Recv_Vel_z[Total_Index];
10903  }
10904 
10905  }
10906  }
10907 
10908  }
10909 
10910  }
10911 
10912  /*--- Reverse in the Y direction to move the solution from 3D to 2D ---*/
10913 
10914  yCoord_CG = -yCoord_CG;
10915  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10916  for (iStation = 0; iStation < nStation; iStation++) {
10917  ProbeArray[iAngle][iStation][9] = -ProbeArray[iAngle][iStation][9];
10918  ProbeArray[iAngle][iStation][1] = -ProbeArray[iAngle][iStation][1];
10919  }
10920  }
10921 
10922  if (output) {
10923 
10924  if (config->GetTabular_FileFormat() == TAB_CSV) {
10925 
10926  SurfFlow_file << "\nDATASET UNSTRUCTURED_GRID" << endl;
10927  SurfFlow_file <<"POINTS " << nAngle*nStation << " float" << endl;
10928  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10929  for (iStation = 0; iStation < nStation; iStation++) {
10930  SurfFlow_file << ProbeArray[iAngle][iStation][1]-yCoord_CG << " " << ProbeArray[iAngle][iStation][2]-zCoord_CG << " 0.0 " <<" ";
10931  }
10932  }
10933 
10934  SurfFlow_file <<"\nCELLS " << nAngle*(nStation-1) <<" "<< nAngle*(nStation-1)*5 << endl;
10935  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10936  for (iStation = 0; iStation < nStation-1; iStation++) {
10937  a = iAngle*nStation+iStation; b = a + nStation; c = b+1; d = a +1;
10938  if (iAngle == nAngle-1) { b = iStation; c = b+1; }
10939  SurfFlow_file << "4 " << a <<" "<< b <<" "<< c <<" "<< d <<" ";
10940  }
10941  }
10942 
10943  SurfFlow_file <<"\nCELL_TYPES " << nAngle*(nStation-1) << endl;
10944  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10945  for (iStation = 0; iStation < nStation-1; iStation++) {
10946  SurfFlow_file << "9 " ;
10947  }
10948  }
10949 
10950  SurfFlow_file <<"\nPOINT_DATA " << nAngle*nStation << endl;
10951  SurfFlow_file <<"SCALARS PT/PT_inf float" << endl;
10952  SurfFlow_file <<"LOOKUP_TABLE default" << endl;
10953 
10954  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10955  for (iStation = 0; iStation < nStation; iStation++) {
10956  SurfFlow_file << ProbeArray[iAngle][iStation][3] << " ";
10957  }
10958  }
10959 
10960  SurfFlow_file <<"SCALARS TT/TT_inf float" << endl;
10961  SurfFlow_file <<"LOOKUP_TABLE default" << endl;
10962 
10963  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10964  for (iStation = 0; iStation < nStation; iStation++) {
10965  SurfFlow_file << ProbeArray[iAngle][iStation][4] << " ";
10966  }
10967  }
10968 
10969  SurfFlow_file <<"SCALARS Alpha float" << endl;
10970  SurfFlow_file <<"LOOKUP_TABLE default" << endl;
10971 
10972  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10973  for (iStation = 0; iStation < nStation; iStation++) {
10974  Alpha = atan(ProbeArray[iAngle][iStation][10]/ProbeArray[iAngle][iStation][8])*360.0/(2.0*PI_NUMBER);
10975  SurfFlow_file << Alpha << " ";
10976  }
10977  }
10978 
10979  SurfFlow_file <<"SCALARS Beta float" << endl;
10980  SurfFlow_file <<"LOOKUP_TABLE default" << endl;
10981 
10982  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10983  for (iStation = 0; iStation < nStation; iStation++) {
10984  Beta = atan(ProbeArray[iAngle][iStation][9]/ProbeArray[iAngle][iStation][8])*360.0/(2.0*PI_NUMBER);
10985  SurfFlow_file << Beta << " ";
10986  }
10987  }
10988 
10989  SurfFlow_file <<"SCALARS Mach float" << endl;
10990  SurfFlow_file <<"LOOKUP_TABLE default" << endl;
10991 
10992  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10993  for (iStation = 0; iStation < nStation; iStation++) {
10994  SurfFlow_file << ProbeArray[iAngle][iStation][7] << " ";
10995  }
10996  }
10997 
10998  SurfFlow_file <<"VECTORS Velocity float" << endl;
10999 
11000  for (iAngle = 0; iAngle < nAngle; iAngle++) {
11001  for (iStation = 0; iStation < nStation; iStation++) {
11002  SurfFlow_file << ProbeArray[iAngle][iStation][8] << " " << ProbeArray[iAngle][iStation][9] << " " << ProbeArray[iAngle][iStation][10] << " ";
11003  }
11004  }
11005 
11006  }
11007  else {
11008 
11009  SurfFlow_file <<"ZONE T= \"" << Analyze_TagBound <<"\", NODES=" << nAngle*nStation << " , ELEMENTS= " << nAngle*(nStation-1) <<", DATAPACKING=POINT, ZONETYPE=FEQUADRILATERAL" << endl;
11010 
11011  for (iAngle = 0; iAngle < nAngle; iAngle++) {
11012  for (iStation = 0; iStation < nStation; iStation++) {
11013 
11014  Alpha = atan(ProbeArray[iAngle][iStation][10]/ProbeArray[iAngle][iStation][8])*360.0/(2.0*PI_NUMBER);
11015  Beta = atan(ProbeArray[iAngle][iStation][9]/ProbeArray[iAngle][iStation][8])*360.0/(2.0*PI_NUMBER);
11016 
11017  Mach_ij = ProbeArray[iAngle][iStation][7];
11018  if (iAngle+1 != nAngle) Mach_ip1j = ProbeArray[iAngle+1][iStation][7];
11019  else Mach_ip1j = ProbeArray[0][iStation][7];
11020  if (iAngle-1 != -1) Mach_im1j = ProbeArray[iAngle-1][iStation][7];
11021  else Mach_im1j = ProbeArray[nAngle-1][iStation][7];
11022  if (iStation+1 != nStation) Mach_ijp1 = ProbeArray[iAngle][iStation+1][7];
11023  else Mach_ijp1 = ProbeArray[iAngle][0][7];
11024  if (iStation-1 != -1) Mach_ijm1 = ProbeArray[iAngle][iStation-1][7];
11025  else Mach_ijm1 = ProbeArray[iAngle][nStation-1][7];
11026  Filtered_Mach = (4.0*Mach_ij+Mach_ip1j+Mach_im1j+Mach_ijp1+Mach_ijm1)/8.0;
11027 
11028  Alpha_ij = atan(ProbeArray[iAngle][iStation][10]/ProbeArray[iAngle][iStation][8])*360.0/(2.0*PI_NUMBER);
11029  if (iAngle+1 != nAngle) Alpha_ip1j = atan(ProbeArray[iAngle+1][iStation][10]/ProbeArray[iAngle+1][iStation][8])*360.0/(2.0*PI_NUMBER);
11030  else Alpha_ip1j = atan(ProbeArray[0][iStation][10]/ProbeArray[0][iStation][8])*360.0/(2.0*PI_NUMBER);
11031  if (iAngle-1 != -1) Alpha_im1j = atan(ProbeArray[iAngle-1][iStation][10]/ProbeArray[iAngle-1][iStation][8])*360.0/(2.0*PI_NUMBER);
11032  else Alpha_im1j = atan(ProbeArray[nAngle-1][iStation][10]/ProbeArray[nAngle-1][iStation][8])*360.0/(2.0*PI_NUMBER);
11033  if (iStation+1 != nStation) Alpha_ijp1 = atan(ProbeArray[iAngle][iStation+1][10]/ProbeArray[iAngle][iStation+1][8])*360.0/(2.0*PI_NUMBER);
11034  else Alpha_ijp1 = atan(ProbeArray[iAngle][0][10]/ProbeArray[iAngle][0][8])*360.0/(2.0*PI_NUMBER);
11035  if (iStation-1 != -1) Alpha_ijm1 = atan(ProbeArray[iAngle][iStation-1][10]/ProbeArray[iAngle][iStation-1][8])*360.0/(2.0*PI_NUMBER);
11036  else Alpha_ijm1 = atan(ProbeArray[iAngle][nStation-1][10]/ProbeArray[iAngle][nStation-1][8])*360.0/(2.0*PI_NUMBER);
11037  Filtered_Alpha = (4.0*Alpha_ij+Alpha_ip1j+Alpha_im1j+Alpha_ijp1+Alpha_ijm1)/8.0;
11038 
11039  Beta_ij = atan(ProbeArray[iAngle][iStation][9]/ProbeArray[iAngle][iStation][8])*360.0/(2.0*PI_NUMBER);
11040  if (iAngle+1 != nAngle) Beta_ip1j = atan(ProbeArray[iAngle+1][iStation][9]/ProbeArray[iAngle+1][iStation][8])*360.0/(2.0*PI_NUMBER);
11041  else Beta_ip1j = atan(ProbeArray[0][iStation][9]/ProbeArray[0][iStation][8])*360.0/(2.0*PI_NUMBER);
11042  if (iAngle-1 != -1) Beta_im1j = atan(ProbeArray[iAngle-1][iStation][9]/ProbeArray[iAngle-1][iStation][8])*360.0/(2.0*PI_NUMBER);
11043  else Beta_im1j = atan(ProbeArray[nAngle-1][iStation][9]/ProbeArray[nAngle-1][iStation][8])*360.0/(2.0*PI_NUMBER);
11044  if (iStation+1 != nStation) Beta_ijp1 = atan(ProbeArray[iAngle][iStation+1][9]/ProbeArray[iAngle][iStation+1][8])*360.0/(2.0*PI_NUMBER);
11045  else Beta_ijp1 = atan(ProbeArray[iAngle][0][9]/ProbeArray[iAngle][0][8])*360.0/(2.0*PI_NUMBER);
11046  if (iStation-1 != -1) Beta_ijm1 = atan(ProbeArray[iAngle][iStation-1][9]/ProbeArray[iAngle][iStation-1][8])*360.0/(2.0*PI_NUMBER);
11047  else Beta_ijm1 = atan(ProbeArray[iAngle][nStation-1][9]/ProbeArray[iAngle][nStation-1][8])*360.0/(2.0*PI_NUMBER);
11048  Filtered_Beta = (4.0*Beta_ij+Beta_ip1j+Beta_im1j+Beta_ijp1+Beta_ijm1)/8.0;
11049 
11050 
11051  SurfFlow_file
11052  << " " << ProbeArray[iAngle][iStation][1]-yCoord_CG
11053  <<" " << ProbeArray[iAngle][iStation][2]-zCoord_CG
11054  <<" " << ProbeArray[iAngle][iStation][3] <<" " << ProbeArray[iAngle][iStation][4]
11055  <<" " << ProbeArray[iAngle][iStation][5] <<" " << ProbeArray[iAngle][iStation][6]
11056  <<" " << ProbeArray[iAngle][iStation][8] <<" " << ProbeArray[iAngle][iStation][9]
11057  <<" " << ProbeArray[iAngle][iStation][10]
11058  <<" " << Alpha <<" " << Beta << " " << ProbeArray[iAngle][iStation][7]
11059  <<" " << Filtered_Alpha <<" " << Filtered_Beta << " " << Filtered_Mach << endl;
11060 
11061  }
11062  }
11063 
11064  for (iAngle = 0; iAngle < nAngle; iAngle++) {
11065  for (iStation = 0; iStation < nStation-1; iStation++) {
11066  a = iAngle*nStation+iStation; b = a + nStation; c = b+1; d = a +1;
11067  if (iAngle == nAngle-1) { b = iStation; c = b+1; }
11068  SurfFlow_file << a+1 <<" "<< b+1 <<" "<< c+1 <<" "<< d+1 << endl;
11069  }
11070  }
11071 
11072  /*--- Add extra info ---*/
11073 
11074  SurfFlow_file << "TEXT X=14, Y=86, F=HELV-BOLD, C=BLUE, H=2.0, ";
11075  unsigned short RackProbes = SU2_TYPE::Int(config->GetDistortionRack()[0]);
11076  unsigned short RackAngle = SU2_TYPE::Int(config->GetDistortionRack()[1]);
11077  SurfFlow_file << "T=\"Rack Size: " << RackProbes << " probes at "<< RackAngle << "deg." << "\\" << "\\n";
11078  SurfFlow_file << "Mach " << config->GetMach() << ", Reynolds " << config->GetReynolds() << ", <greek>a</greek> "
11079  << config->GetAoA() << "deg, <greek>b</greek> " << config->GetAoS() << "deg." << "\\" << "\\n";
11080  SurfFlow_file.precision(1);
11081  SurfFlow_file << fixed << "Net Thrust " << solver->GetTotal_NetThrust() << "lbs, Power " << solver->GetTotal_Power() << "HP";
11082  SurfFlow_file.precision(4);
11083  SurfFlow_file << ", MassFlow " << config->GetSurface_MassFlow(iMarker_Analyze) << ",\\" << "\\n";
11084  SurfFlow_file << "IDC " << config->GetSurface_IDC(iMarker_Analyze)*100 << "%, IDCM " << config->GetSurface_IDC_Mach(iMarker_Analyze)*100 << "%, IDR " << config->GetSurface_IDR(iMarker_Analyze)*100 << "%,\\" << "\\n";
11085  SurfFlow_file << "DC60 " << config->GetSurface_DC60(iMarker_Analyze) << ".\"" << endl;
11086 
11087  }
11088 
11089  }
11090 
11091  /*--- Release the recv buffers on the master node ---*/
11092 
11093  delete [] Buffer_Recv_Coord_x;
11094  delete [] Buffer_Recv_Coord_y;
11095  if (nDim == 3) delete [] Buffer_Recv_Coord_z;
11096 
11097  delete [] Buffer_Recv_PT;
11098  delete [] Buffer_Recv_TT;
11099  delete [] Buffer_Recv_P;
11100  delete [] Buffer_Recv_T;
11101  delete [] Buffer_Recv_Mach;
11102  delete [] Buffer_Recv_Vel_x;
11103  delete [] Buffer_Recv_Vel_y;
11104  if (nDim == 3) delete [] Buffer_Recv_Vel_z;
11105  delete [] Buffer_Recv_q;
11106 
11107  delete [] Buffer_Recv_Area;
11108 
11109  delete [] Buffer_Recv_nVertex;
11110 
11111  delete[] r;
11112  for (iAngle = 0; iAngle < nAngle; iAngle++) {
11113  for (iStation = 0; iStation < nStation; iStation++) {
11114  delete[] ProbeArray[iAngle][iStation];
11115  }
11116  }
11117  delete[] ProbeArray;
11118 
11119  }
11120 
11121 // if ((rank == MASTER_NODE) && !config->GetDiscrete_Adjoint()) {
11122 //
11123 // cout << "Surface ("<< Analyze_TagBound << "): ";
11124 // cout.precision(4);
11125 // cout.setf(ios::fixed, ios::floatfield);
11126 // cout << setprecision(1) << "IDC " << 100*config->GetSurface_IDC(iMarker_Analyze)
11127 // << "%. IDC Mach " << 100*config->GetSurface_IDC_Mach(iMarker_Analyze)
11128 // << "%. IDR " << 100*config->GetSurface_IDR(iMarker_Analyze)
11129 // << "%. DC60 " << config->GetSurface_DC60(iMarker_Analyze) << "." << endl;
11130 //
11131 // }
11132 
11133  /*--- Release the memory for the remaining buffers and exit ---*/
11134 
11135  delete [] Buffer_Send_Coord_x;
11136  delete [] Buffer_Send_Coord_y;
11137  if (nDim == 3) delete [] Buffer_Send_Coord_z;
11138 
11139  delete [] Buffer_Send_PT;
11140  delete [] Buffer_Send_TT;
11141  delete [] Buffer_Send_P;
11142  delete [] Buffer_Send_T;
11143  delete [] Buffer_Send_Mach;
11144  delete [] Buffer_Send_Vel_x;
11145  delete [] Buffer_Send_Vel_y;
11146  if (nDim == 3) delete [] Buffer_Send_Vel_z;
11147  delete [] Buffer_Send_q;
11148 
11149  delete [] Buffer_Send_Area;
11150 
11151  }
11152 
11153  /*--- Close the tecplot file ---*/
11154 
11155  if (output) {
11156  SurfFlow_file.close();
11157  }
11158 
11159 }
11160 
11161 void COutputLegacy::SpecialOutput_FSI(ofstream *FSIHist_file, CGeometry ****geometry, CSolver *****solver_container,
11162  CConfig **config, CIntegration ****integration, unsigned long iExtIter,
11163  unsigned short ZONE_FLOW, unsigned short ZONE_STRUCT, bool header) {
11164 
11165  int rank = MASTER_NODE;
11166 #ifdef HAVE_MPI
11167  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
11168 #endif
11169 
11170  /*--- Output only using the Master Node ---*/
11171 
11172  if ((rank == MASTER_NODE) && (header)){
11173 
11174  char cstr[200], buffer[50], turb_resid[1000];
11175  string Monitoring_Tag, monitoring_coeff, aeroelastic_coeff, turbo_coeff;
11176 
11177  bool turbulent = ((config[ZONE_FLOW]->GetKind_Solver() == RANS) || (config[ZONE_FLOW]->GetKind_Solver() == ADJ_RANS) ||
11178  (config[ZONE_FLOW]->GetKind_Solver() == DISC_ADJ_RANS));
11179 
11180  unsigned short direct_diff = config[ZONE_FLOW]->GetDirectDiff();
11181 
11182  /*--- Write file name with extension ---*/
11183 // string filename = config[ZONE_FLOW]->GetConv_FileName_FSI();
11184 // strcpy (cstr, filename.data());
11185 
11186  if (config[ZONE_FLOW]->GetTime_Domain() && config[ZONE_FLOW]->GetRestart()) {
11187  long iExtIter = config[ZONE_FLOW]->GetRestart_Iter();
11188  if (SU2_TYPE::Int(iExtIter) < 10) SPRINTF (buffer, "_0000%d", SU2_TYPE::Int(iExtIter));
11189  if ((SU2_TYPE::Int(iExtIter) >= 10) && (SU2_TYPE::Int(iExtIter) < 100)) SPRINTF (buffer, "_000%d", SU2_TYPE::Int(iExtIter));
11190  if ((SU2_TYPE::Int(iExtIter) >= 100) && (SU2_TYPE::Int(iExtIter) < 1000)) SPRINTF (buffer, "_00%d", SU2_TYPE::Int(iExtIter));
11191  if ((SU2_TYPE::Int(iExtIter) >= 1000) && (SU2_TYPE::Int(iExtIter) < 10000)) SPRINTF (buffer, "_0%d", SU2_TYPE::Int(iExtIter));
11192  if (SU2_TYPE::Int(iExtIter) >= 10000) SPRINTF (buffer, "_%d", SU2_TYPE::Int(iExtIter));
11193  strcat(cstr, buffer);
11194  }
11195 
11196  if ((config[ZONE_FLOW]->GetTabular_FileFormat() == TAB_TECPLOT)) SPRINTF (buffer, ".dat");
11197  else if ((config[ZONE_FLOW]->GetTabular_FileFormat() == TAB_CSV)) SPRINTF (buffer, ".vtk");
11198  strcat(cstr, buffer);
11199 
11200  FSIHist_file->open(cstr, ios::out);
11201  FSIHist_file->precision(15);
11202 
11203  /*--- Begin of the header ---*/
11204 
11205  char begin[]= "\"ExtIter\",\"BGSIter\"";
11206 
11207  /*--- Header for the coefficients ---*/
11208 
11209  char flow_coeff[]= ",\"CL\",\"CD\",\"CMx\",\"CMy\",\"CMz\",\"CL/CD\"";
11210  char fem_coeff[]= ",\"VM_Stress\"";
11211  char of_1[] = ",\"TgtGeom\"";
11212  char of_2[] = ",\"TgtNode\"";
11213 
11214  char d_flow_coeff[] = ",\"D(CL)\",\"D(CD)\",\"D(CSF)\",\"D(CMx)\",\"D(CMy)\",\"D(CMz)\",\"D(CFx)\",\"D(CFy)\",\"D(CFz)\",\"D(CL/CD)\",\"D(Custom_ObjFunc)\"";
11215 
11216  /*--- Header for the residuals ---*/
11217 
11218  char fsi_resid[]= ",\"Res_FSI\",\"RelaxCoeff\",\"ForceCoeff\"";
11219 
11220  char flow_resid[]= ",\"Res_BGS[F0]\",\"Res_BGS[F1]\",\"Res_BGS[F2]\",\"Res_BGS[F3]\",\"Res_BGS[F4]\"";
11221  char adj_flow_resid[]= ",\"Res_AdjFlow[0]\",\"Res_AdjFlow[1]\",\"Res_AdjFlow[2]\",\"Res_AdjFlow[3]\",\"Res_AdjFlow[4]\"";
11222  char fem_resid[]= ",\"Res_BGS[S0]\",\"Res_BGS[S1]\",\"Res_BGS[S2]\"";
11223 
11224  /*--- End of the header ---*/
11225 
11226  char end[]= ",\"Time(min)\"\n";
11227 
11228  if ((config[ZONE_FLOW]->GetTabular_FileFormat() == TECPLOT) ||
11229  (config[ZONE_FLOW]->GetTabular_FileFormat() == TECPLOT_BINARY)) {
11230  FSIHist_file[0] << "TITLE = \"SU2 FSI Simulation\"" << endl;
11231  FSIHist_file[0] << "VARIABLES = ";
11232  }
11233 
11234  /*--- Write the header, case depending ---*/
11235 
11236  FSIHist_file[0] << begin;
11237 
11238  FSIHist_file[0] << fsi_resid;
11239 
11240  switch (config[ZONE_FLOW]->GetKind_Solver()) {
11241 
11242  /*--- Flow residual output ---*/
11243 
11244  case EULER : case NAVIER_STOKES: case RANS :
11245  case INC_EULER : case INC_NAVIER_STOKES: case INC_RANS :
11246  FSIHist_file[0] << flow_resid;
11247  if (turbulent) FSIHist_file[0] << turb_resid;
11248  break;
11249 
11252  FSIHist_file[0] << adj_flow_resid;
11253  break;
11254 
11255  }
11256 
11257  /*--- FEA residual output ---*/
11258 
11259  switch (config[ZONE_STRUCT]->GetKind_Solver()) {
11260 
11261  case FEM_ELASTICITY:
11262  FSIHist_file[0] << fem_resid;
11263  break;
11264 
11265  case DISC_ADJ_FEM:
11266  FSIHist_file[0] << fem_resid ;
11267  break;
11268 
11269  }
11270 
11271  /*--- Flow coefficients output ---*/
11272  switch (config[ZONE_FLOW]->GetKind_Solver()) {
11273 
11274  case EULER : case NAVIER_STOKES: case RANS :
11275  case INC_EULER : case INC_NAVIER_STOKES: case INC_RANS :
11276  FSIHist_file[0] << flow_coeff;
11277  if (turbulent) FSIHist_file[0] << turb_resid;
11278  if (direct_diff != NO_DERIVATIVE) {
11279  FSIHist_file[0] << d_flow_coeff;
11280  }
11281  break;
11282 
11285  FSIHist_file[0] << adj_flow_resid;
11286  break;
11287 
11288  }
11289 
11290  switch (config[ZONE_STRUCT]->GetKind_Solver()) {
11291 
11292  case FEM_ELASTICITY:
11293  FSIHist_file[0] << fem_coeff;
11294  break;
11295 
11296  case DISC_ADJ_FEM:
11297  FSIHist_file[0] << fem_coeff;
11298  break;
11299 
11300  }
11301 
11302  switch (config[ZONE_STRUCT]->GetKind_ObjFunc()){
11303  case REFERENCE_GEOMETRY:
11304  FSIHist_file[0] << of_1;
11305  break;
11306  case REFERENCE_NODE:
11307  FSIHist_file[0] << of_2;
11308  break;
11309  default:
11310  break;
11311  }
11312 
11313  FSIHist_file[0] << end;
11314 
11315 
11316  }
11317 
11318  if ((rank == MASTER_NODE) && (!header)){
11319 
11320  unsigned short nDim = geometry[ZONE_STRUCT][INST_0][MESH_0]->GetnDim();
11321 
11322  unsigned long iExtIter = config[ZONE_STRUCT]->GetInnerIter();
11323  unsigned long ExtIter_OffSet = config[ZONE_STRUCT]->GetExtIter_OffSet();
11324  unsigned long iOuterIter = config[ZONE_STRUCT]->GetOuterIter();
11325  su2double dummy = 0.0;
11326 
11327  bool first_iter = ((iExtIter==0) && (iOuterIter == 0));
11328 
11329 
11330  bool compressible = (config[ZONE_FLOW]->GetKind_Regime() == COMPRESSIBLE);
11331  bool incompressible = (config[ZONE_FLOW]->GetKind_Regime() == INCOMPRESSIBLE);
11332 
11333 
11334  bool fem = ((config[ZONE_STRUCT]->GetKind_Solver() == FEM_ELASTICITY) ||
11335  (config[ZONE_STRUCT]->GetKind_Solver() == DISC_ADJ_FEM));
11336  bool linear_analysis = (config[ZONE_STRUCT]->GetGeometricConditions() == SMALL_DEFORMATIONS);
11337  bool nonlinear_analysis = (config[ZONE_STRUCT]->GetGeometricConditions() == LARGE_DEFORMATIONS);
11338 
11339  bool disc_adj_flow = config[ZONE_FLOW]->GetDiscrete_Adjoint();
11340  bool disc_adj_fem = config[ZONE_STRUCT]->GetDiscrete_Adjoint();
11341 
11342 
11343  /*--- WARNING: These buffers have hard-coded lengths. Note that you
11344  may have to adjust them to be larger if adding more entries. ---*/
11345 
11346  char begin[1000], direct_coeff[1000],
11347  fsi_resid[1000], fsi_coeffs[1000],
11348  flow_resid[1000], fem_resid[1000],
11349  objective_function[1000], end[1000];
11350 
11351  su2double *residual_flow = NULL;
11352  su2double *residual_fem = NULL;
11353  su2double *residual_fsi = NULL;
11354  su2double *coeffs_fsi = NULL;
11355 
11356  /*--- Initialize number of variables ---*/
11357  unsigned short nVar_FSI = 1, nCoeff_FSI = 2, nVar_Flow = 0, nVar_FEM = 0;
11358 
11359  unsigned short iVar;
11360 
11361  /*--- Direct problem variables ---*/
11362  if (compressible) nVar_Flow = nDim+2; else nVar_Flow = nDim+1;
11363 
11364  if (fem) {
11365  if (linear_analysis) nVar_FEM = nDim;
11366  if (nonlinear_analysis) nVar_FEM = 3;
11367  if (disc_adj_fem) nVar_FEM = nDim;
11368  }
11369 
11370  residual_flow = new su2double[nVar_Flow];
11371  residual_fem = new su2double[nVar_FEM];
11372  residual_fsi = new su2double[nVar_FSI];
11373  coeffs_fsi = new su2double[nCoeff_FSI];
11374 
11375  /*--- Initialize variables to store information from all domains (direct solution) ---*/
11376 
11377  su2double Total_CL = 0.0, Total_CD = 0.0, Total_CMx = 0.0, Total_CMy = 0.0, Total_CMz = 0.0, Total_CEff = 0.0,
11378  Total_OF = 0.0;
11379 
11380  Total_CL = solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->GetTotal_CL();
11381  Total_CD = solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->GetTotal_CD();
11382  Total_CEff = solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->GetTotal_CEff();
11383  Total_CMx = solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->GetTotal_CMx();
11384  Total_CMy = solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->GetTotal_CMy();
11385  Total_CMz = solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->GetTotal_CMz();
11386 
11387  bool print_of = false;
11388 
11389  switch (config[ZONE_STRUCT]->GetKind_ObjFunc()){
11390  case REFERENCE_GEOMETRY:
11391  Total_OF = solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetTotal_OFRefGeom();
11392  print_of = true;
11393  break;
11394  case REFERENCE_NODE:
11395  Total_OF = solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetTotal_OFRefNode();
11396  print_of = true;
11397  break;
11398  default:
11399  break;
11400  }
11401 
11402  if ((!disc_adj_flow) && (!disc_adj_fem)){
11403  /*--- Flow Residuals ---*/
11404  for (iVar = 0; iVar < nVar_Flow; iVar++)
11405  residual_flow[iVar] = solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->GetRes_BGS(iVar);
11406 
11407  /*--- FEA Residuals ---*/
11408  for (iVar = 0; iVar < nVar_FEM; iVar++)
11409  residual_fem[iVar] = solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetRes_BGS(iVar);
11410 
11411  residual_fsi[0] = solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetFSI_Residual();
11412  coeffs_fsi[0] = solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetRelaxCoeff();
11413  coeffs_fsi[1] = solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetForceCoeff();
11414 
11415  }
11416  else{
11417  /*--- Flow Residuals ---*/
11418  for (iVar = 0; iVar < nVar_Flow; iVar++)
11419  residual_flow[iVar] = solver_container[ZONE_FLOW][INST_0][MESH_0][ADJFLOW_SOL]->GetRes_BGS(iVar);
11420  /*--- FEA Residuals ---*/
11421  for (iVar = 0; iVar < nVar_FEM; iVar++)
11422  residual_fem[iVar] = solver_container[ZONE_STRUCT][INST_0][MESH_0][ADJFEA_SOL]->GetRes_BGS(iVar);
11423  }
11424 
11425  /*--- Write the begining of the history file ---*/
11426  SPRINTF(begin, "%12d, %12d", SU2_TYPE::Int(iExtIter+ExtIter_OffSet), SU2_TYPE::Int(iOuterIter));
11427  /*--- Write the end of the history file ---*/
11428  SPRINTF (end, "\n");
11429 
11430  SPRINTF (fsi_resid, ", %14.8e", log10 (residual_fsi[0]));
11431  SPRINTF (fsi_coeffs, ", %14.8e, %14.8e", coeffs_fsi[0], coeffs_fsi[1]);
11432 
11433  /*--- Flow residual ---*/
11434  if (nDim == 2) {
11435  if (compressible) SPRINTF (flow_resid, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", log10 (residual_flow[0]), log10 (residual_flow[1]), log10 (residual_flow[2]), log10 (residual_flow[3]), dummy);
11436  if (incompressible) SPRINTF (flow_resid, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", log10 (residual_flow[0]), log10 (residual_flow[1]), log10 (residual_flow[2]), dummy, dummy);
11437  }
11438  else {
11439  if (compressible) SPRINTF (flow_resid, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", log10 (residual_flow[0]), log10 (residual_flow[1]), log10 (residual_flow[2]), log10 (residual_flow[3]), log10 (residual_flow[4]) );
11440  if (incompressible) SPRINTF (flow_resid, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", log10 (residual_flow[0]), log10 (residual_flow[1]), log10 (residual_flow[2]), log10 (residual_flow[3]), dummy);
11441  }
11442 
11443  /*--- FEM residual ---*/
11444  if (nDim == 2) SPRINTF (fem_resid, ", %14.8e, %14.8e, %14.8e", log10 (residual_fem[0]), log10 (residual_fem[1]), dummy);
11445  else SPRINTF (fem_resid, ", %14.8e, %14.8e, %14.8e", log10 (residual_fem[0]), log10 (residual_fem[1]), log10 (residual_fem[1]));
11446 
11447  /*--- Direct coefficients ---*/
11448  SPRINTF (direct_coeff, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e",Total_CL, Total_CD, Total_CMx, Total_CMy, Total_CMz, Total_CEff);
11449 
11450  if (print_of) SPRINTF (objective_function, ", %14.8e", Total_OF);
11451 
11452  if (!first_iter){
11453  if (!print_of) FSIHist_file[0] << begin << fsi_resid << fsi_coeffs << flow_resid << fem_resid << direct_coeff << end;
11454  else FSIHist_file[0] << begin << fsi_resid << fsi_coeffs << flow_resid << fem_resid << direct_coeff << objective_function << end;
11455  FSIHist_file[0].flush();
11456  }
11457 
11458  delete [] residual_flow;
11459  delete [] residual_fem;
11460  delete [] residual_fsi;
11461  delete [] coeffs_fsi;
11462 
11463 
11464  }
11465 
11466 }
11467 
11468 void COutputLegacy::SetSensitivity_Files(CGeometry ***geometry, CConfig **config, unsigned short val_nZone) {
11469 
11470  unsigned short iMarker,iDim, nDim, iVar, nMarker, nVar;
11471  unsigned long iVertex, iPoint, nPoint, nVertex;
11472  su2double *Normal, Prod, Sens = 0.0, SensDim, Area;
11473 
11474  unsigned short iZone;
11475 
11476  CSolver ***solver = new CSolver**[val_nZone];
11477  for (iZone = 0; iZone < val_nZone; iZone++) {
11478  solver[iZone] = new CSolver*[1];
11479  }
11480 
11481  for (iZone = 0; iZone < val_nZone; iZone++) {
11482 
11483  nPoint = geometry[iZone][INST_0]->GetnPoint();
11484  nDim = geometry[iZone][INST_0]->GetnDim();
11485  nMarker = config[iZone]->GetnMarker_All();
11486  nVar = nDim + 1;
11487 
11488  /*--- We create a baseline solver to easily merge the sensitivity information ---*/
11489 
11490  vector<string> fieldnames;
11491  fieldnames.push_back("\"Point\"");
11492  fieldnames.push_back("\"x\"");
11493  fieldnames.push_back("\"y\"");
11494  if (nDim == 3) {
11495  fieldnames.push_back("\"z\"");
11496  }
11497  fieldnames.push_back("\"Sensitivity_x\"");
11498  fieldnames.push_back("\"Sensitivity_y\"");
11499  if (nDim == 3) {
11500  fieldnames.push_back("\"Sensitivity_z\"");
11501  }
11502  fieldnames.push_back("\"Surface_Sensitivity\"");
11503 
11504  solver[iZone][INST_0] = new CBaselineSolver(geometry[iZone][INST_0], config[iZone], nVar+nDim, fieldnames);
11505 
11506  for (iPoint = 0; iPoint < nPoint; iPoint++) {
11507  for (iDim = 0; iDim < nDim; iDim++) {
11508  solver[iZone][INST_0]->GetNodes()->SetSolution(iPoint, iDim, geometry[iZone][INST_0]->node[iPoint]->GetCoord(iDim));
11509  }
11510  for (iVar = 0; iVar < nDim; iVar++) {
11511  solver[iZone][INST_0]->GetNodes()->SetSolution(iPoint, iVar+nDim, geometry[iZone][INST_0]->GetSensitivity(iPoint, iVar));
11512  }
11513  }
11514 
11515  /*--- Compute the sensitivity in normal direction ---*/
11516 
11517  for (iMarker = 0; iMarker < nMarker; iMarker++) {
11518 
11519  if((config[iZone]->GetMarker_All_KindBC(iMarker) == HEAT_FLUX ) ||
11520  (config[iZone]->GetMarker_All_KindBC(iMarker) == EULER_WALL ) ||
11521  (config[iZone]->GetMarker_All_KindBC(iMarker) == ISOTHERMAL ) ||
11522  (config[iZone]->GetMarker_All_KindBC(iMarker) == CHT_WALL_INTERFACE )) {
11523 
11524 
11525  nVertex = geometry[iZone][INST_0]->GetnVertex(iMarker);
11526 
11527  for (iVertex = 0; iVertex < nVertex; iVertex++) {
11528  iPoint = geometry[iZone][INST_0]->vertex[iMarker][iVertex]->GetNode();
11529  Normal = geometry[iZone][INST_0]->vertex[iMarker][iVertex]->GetNormal();
11530  Prod = 0.0;
11531  Area = 0.0;
11532  for (iDim = 0; iDim < nDim; iDim++) {
11533 
11534  /*--- Retrieve the gradient calculated with discrete adjoint method ---*/
11535 
11536  SensDim = geometry[iZone][INST_0]->GetSensitivity(iPoint, iDim);
11537 
11538  /*--- Calculate scalar product for projection onto the normal vector ---*/
11539 
11540  Prod += Normal[iDim]*SensDim;
11541 
11542  Area += Normal[iDim]*Normal[iDim];
11543  }
11544 
11545  Area = sqrt(Area);
11546 
11547  /*--- Projection of the gradient onto the normal vector of the surface ---*/
11548 
11549  Sens = Prod/Area;
11550 
11551  solver[iZone][INST_0]->GetNodes()->SetSolution(iPoint, 2*nDim, Sens);
11552 
11553  }
11554  }
11555  }
11556  }
11557 
11558  /*--- Merge the information and write the output files ---*/
11559 
11560  SetBaselineResult_Files(solver, geometry, config, 0, val_nZone);
11561 
11562  for (iZone = 0; iZone < val_nZone; iZone++) {
11563  delete solver[iZone][0];
11564  delete solver[iZone];
11565  }
11566  delete [] solver;
11567 }
11568 
11570 
11571  unsigned short iMarker_Monitoring;
11572  string inMarker_Tag, outMarker_Tag, inMarkerTag_Mix;
11573  unsigned short nZone = config->GetnZone();
11574  bool turbulent = ((config->GetKind_Solver() == RANS) || (config->GetKind_Solver() == DISC_ADJ_RANS));
11575  bool menter_sst = (config->GetKind_Turb_Model() == SST) || (config->GetKind_Turb_Model() == SST_SUST);
11576 
11577  unsigned short nBladesRow, nStages;
11578  unsigned short iStage;
11579  nBladesRow = config->GetnMarker_Turbomachinery();
11580  nStages = SU2_TYPE::Int(nBladesRow/2);
11581 
11582  cout << endl << "------------------------- Turbomachinery Summary ------------------------" << endl;
11583  cout << endl;
11584  for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Turbomachinery(); iMarker_Monitoring++){
11585  cout << endl << "----------------------------- Blade " << iMarker_Monitoring + 1 << " -----------------------------------" << endl;
11586  inMarker_Tag = config->GetMarker_TurboPerf_BoundIn(iMarker_Monitoring);
11587  outMarker_Tag = config->GetMarker_TurboPerf_BoundOut(iMarker_Monitoring);
11588  if(iMarker_Monitoring == 0){
11589  cout << "BC Inlet convergence monitoring marker " << inMarker_Tag << " : "<<endl;
11590  cout << endl;
11591  cout << " Inlet Total Enthalpy" << " Inlet Total Enthalpy BC" << " err(%)" << endl;
11592  cout.width(25); cout << TotalEnthalpyIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*config->GetEnergy_Ref();
11593  cout.width(25); cout << TotalEnthalpyIn_BC[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*config->GetEnergy_Ref();
11594  cout.width(25); cout << abs((TotalEnthalpyIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)] - TotalEnthalpyIn_BC[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)])/TotalEnthalpyIn_BC[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)])*100.0;
11595  cout << endl;
11596  cout << endl;
11597  cout << " Inlet Entropy" << " Inlet Entropy BC" << " err(%)" << endl;
11598  cout.width(25); cout << EntropyIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*config->GetEnergy_Ref()/config->GetTemperature_Ref();
11599  cout.width(25); cout << EntropyIn_BC[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*config->GetEnergy_Ref()/config->GetTemperature_Ref();
11600  cout.width(25); cout << abs((EntropyIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)] - EntropyIn_BC[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)])/EntropyIn_BC[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)])*100.0;
11601  cout << endl;
11602  cout << endl;
11603  cout << " Inlet Absolute Angle" << " Inlet Absolute Angle BC" << " err(%)" << endl;
11604  cout.width(25); cout << 180.0/PI_NUMBER*AbsFlowAngleIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)];
11605  cout.width(25); cout << 180.0/PI_NUMBER*FlowAngleIn_BC[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)];
11606  cout.width(25); cout << abs((AbsFlowAngleIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)] - FlowAngleIn_BC[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)])/FlowAngleIn_BC[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)])*100.0;
11607  cout << endl;
11608  cout << endl;
11609  if(turbulent){
11610  if(menter_sst){
11611  cout << " Inlet TurbIntensity" << " Inlet TurbIntensity BC" << " err(%)" << endl;
11612  cout.width(25); cout << TurbIntensityIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)];
11613  cout.width(25); cout << config->GetTurbulenceIntensity_FreeStream();
11614  cout.width(25); cout << abs((TurbIntensityIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)] - config->GetTurbulenceIntensity_FreeStream())/config->GetTurbulenceIntensity_FreeStream())*100.0;
11615  cout << endl;
11616  cout << endl;
11617  cout << " Inlet Turb2LamRatio" << " Inlet Turb2LamRatio BC" << " err(%)" << endl;
11618  cout.width(25); cout << Turb2LamViscRatioIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)];
11619  cout.width(25); cout << config->GetTurb2LamViscRatio_FreeStream();
11620  cout.width(25); cout << abs((Turb2LamViscRatioIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)] - config->GetTurb2LamViscRatio_FreeStream())/config->GetTurb2LamViscRatio_FreeStream())*100.0;
11621  cout << endl;
11622  cout << endl;
11623  }
11624  else{
11625  cout << " Inlet Nu Factor" << " Inlet Nu Factor BC" << " err(%)" << endl;
11626  cout.width(25); cout << NuFactorIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)];
11627  cout.width(25); cout << config->GetNuFactor_FreeStream();
11628  cout.width(25); cout << abs((NuFactorIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)] - config->GetNuFactor_FreeStream())/config->GetNuFactor_FreeStream())*100.0;
11629  cout << endl;
11630  cout << endl;
11631  }
11632  }
11633  }
11634  if(iMarker_Monitoring == config->GetnMarker_Turbomachinery() -1 ){
11635  // if BC outlet
11636  cout << "BC outlet convergence monitoring marker " << outMarker_Tag << " : "<<endl;
11637  cout << endl;
11638  cout << " Outlet Pressure" << " Outlet Pressure BC" << " err(%)" << endl;
11639  cout.width(25); cout << PressureOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*config->GetPressure_Ref();
11640  cout.width(25); cout << PressureOut_BC[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*config->GetPressure_Ref();
11641  cout.width(25); cout << abs((PressureOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)] - PressureOut_BC[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)])/PressureOut_BC[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)])*100.0;
11642  cout << endl;
11643  cout << endl;
11644  }
11645 
11646  cout << "Convergence monitoring for integral quantities between markers " << inMarker_Tag << " and "<< outMarker_Tag << " : "<<endl;
11647  cout << endl;
11648  cout << " Inlet Mass Flow " << " Outlet Mass Flow" << " err(%)" << endl;
11649  cout.width(25); cout << MassFlowIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*config->GetVelocity_Ref()*config->GetDensity_Ref();
11650  cout.width(25); cout << MassFlowOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*config->GetVelocity_Ref()*config->GetDensity_Ref();
11651  cout.width(25); cout << abs((MassFlowIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)] - MassFlowOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)])/MassFlowIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)])*100.0;
11652  cout << endl;
11653  cout << endl;
11654  //if(stator)
11655  //cout << " Inlet Total Enthalpy " << " Outlet Total Enthalpy" << " err(%)" << endl;
11656  //else
11657  cout << " Inlet Total Rothalpy " << " Outlet Total Rothalpy" << " err(%)" << endl;
11658  cout.width(25); cout << RothalpyIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*config->GetEnergy_Ref();
11659  cout.width(25); cout << RothalpyOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*config->GetEnergy_Ref();
11660  cout.width(25); cout << abs((RothalpyIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)] - RothalpyOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)])/RothalpyIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)])*100.0;
11661  cout << endl;
11662  cout << endl;
11663  cout << "Blade performance between boundaries " << inMarker_Tag << " and "<< outMarker_Tag << " : "<<endl;
11664  cout << endl;
11665  cout << " Total Pressure Loss(%)" << " Kinetic Energy Loss(%)" << " Entropy Generation(%)" << endl;
11666  cout.width(25); cout << TotalPressureLoss[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*100.0;
11667  cout.width(25); cout << KineticEnergyLoss[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*100.0;
11668  cout.width(25); cout << EntropyGen[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*100.0;
11669  cout << endl;
11670  cout << endl;
11671  cout << " Total Inlet Enthalpy" << " Eulerian Work" << " Pressure Ratio" << endl;
11672  cout.width(25); cout << TotalEnthalpyIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*config->GetEnergy_Ref();
11673  cout.width(25); cout << EulerianWork[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*config->GetEnergy_Ref();
11674  cout.width(25); cout << PressureRatio[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)];
11675  cout << endl;
11676  cout << endl;
11677  cout << " Inlet Entropy" << " Outlet Entropy" << " Outlet Is. Enthalpy" << endl;
11678  cout.width(25); cout << EntropyIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*config->GetEnergy_Ref()/config->GetTemperature_Ref();
11679  cout.width(25); cout << EntropyOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*config->GetEnergy_Ref()/config->GetTemperature_Ref();
11680  cout.width(25); cout << EnthalpyOutIs[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*config->GetEnergy_Ref();
11681  cout << endl;
11682  cout << endl;
11683  cout << "Cinematic quantities between boundaries " << inMarker_Tag << " and "<< outMarker_Tag << " : "<<endl;
11684  cout << endl;
11685  cout << " Inlet Mach"<< " Inlet Normal Mach" << " Inlet Tang. Mach" << endl;
11686  cout.width(25); cout << sqrt(MachIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)][0]*MachIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)][0] +MachIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)][1]*MachIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)][1]);
11687  cout.width(25); cout << MachIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)][0];
11688  cout.width(25); cout << MachIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)][1];
11689  cout << endl;
11690  cout << endl;
11691  cout << " Outlet Mach"<< " Outlet Normal Mach" << " Outlet Tang. Mach" << endl;
11692  cout.width(25); cout << sqrt(MachOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)][0]*MachOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)][0] +MachOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)][1]*MachOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)][1]);
11693  cout.width(25); cout << MachOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)][0];
11694  cout.width(25); cout << MachOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)][1];cout << endl;
11695  cout << endl;
11696  cout << " Inlet Flow Angle" << " Outlet flow Angle " << endl;
11697  cout.width(25); cout << 180.0/PI_NUMBER*FlowAngleIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)];
11698  cout.width(25); cout << 180.0/PI_NUMBER*FlowAngleOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)];
11699  cout << endl;
11700  cout << endl;
11701  // if gridmov
11702  cout << " Inlet Abs Flow Angle" << " Outlet Abs Flow Angle " << endl;
11703  cout.width(25); cout << 180.0/PI_NUMBER*AbsFlowAngleIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)];
11704  cout.width(25); cout << 180.0/PI_NUMBER*AbsFlowAngleOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)];
11705  cout << endl;
11706  cout << endl << "-------------------------------------------------------------------------" << endl;
11707  cout << endl;
11708  if(nZone > 0 && iMarker_Monitoring < config->GetnMarker_Turbomachinery() -1){
11709  cout << endl << "---------- Mixing-Plane Interface between Blade " << iMarker_Monitoring + 1 << " and Blade " << iMarker_Monitoring + 2 << " -----------" << endl;
11710  cout << endl;
11711  inMarkerTag_Mix = config->GetMarker_TurboPerf_BoundIn(iMarker_Monitoring + 1);
11712  cout << "Convergence monitoring for the outlet " << outMarker_Tag << " and the inlet "<< inMarkerTag_Mix << " : "<<endl;
11713  cout << endl;
11714  cout << " Outlet Density " << " Inlet Density" << " err(%)" << endl;
11715  cout.width(25); cout << DensityOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*config->GetDensity_Ref();
11716  cout.width(25); cout << DensityIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring + 1)]*config->GetDensity_Ref();
11717  cout.width(25); cout << abs((DensityIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring +1)] - DensityOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)])/DensityIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring +1)])*100.0;
11718  cout << endl;
11719  cout << endl;
11720  cout << " Outlet Pressure " << " Inlet Pressure" << " err(%)" << endl;
11721  cout.width(25); cout << PressureOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*config->GetPressure_Ref();
11722  cout.width(25); cout << PressureIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring +1)]*config->GetPressure_Ref();
11723  cout.width(25); cout << abs((PressureIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring +1)] - PressureOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)])/PressureIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring +1)])*100.0;
11724  cout << endl;
11725  cout << endl;
11726  cout << " Outlet Normal Velocity " << " Inlet Normal Velocity" << " err(%)" << endl;
11727  cout.width(25); cout << TurboVelocityOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)][0]*config->GetVelocity_Ref();
11728  cout.width(25); cout << TurboVelocityIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring +1)][0]*config->GetVelocity_Ref();
11729  cout.width(25); cout << abs((TurboVelocityIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring +1)][0] - TurboVelocityOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)][0])/TurboVelocityIn[iMarker_Monitoring+1][config->GetnSpan_iZones(iMarker_Monitoring +1)][0])*100.0;
11730  cout << endl;
11731  cout << endl;
11732  cout << " Outlet Tang. Velocity " << " Inlet Tang. Velocity" << " err(%)" << endl;
11733  cout.width(25); cout << TurboVelocityOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)][1]*config->GetVelocity_Ref();
11734  cout.width(25); cout << TurboVelocityIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring +1)][1]*config->GetVelocity_Ref();
11735  cout.width(25); cout << abs((TurboVelocityIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring +1)][1] - TurboVelocityOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)][1])/TurboVelocityIn[iMarker_Monitoring+1][config->GetnSpan_iZones(iMarker_Monitoring +1)][1])*100.0;
11736  cout << endl;
11737  cout << endl;
11738  cout << " Outlet Entropy " << " Inlet Entropy" << " err(%)" << endl;
11739  cout.width(25); cout << EntropyOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*config->GetEnergy_Ref()/config->GetTemperature_Ref();
11740  cout.width(25); cout << EntropyIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring +1)]*config->GetEnergy_Ref()/config->GetTemperature_Ref();
11741  cout.width(25); cout << abs((EntropyIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring+1)] - EntropyOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)])/EntropyIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring+1)])*100.0;
11742  if(turbulent){
11743  cout << endl;
11744  cout << endl;
11745  if(menter_sst){
11746  cout << " Outlet TurbIntensity " << " Inlet TurbIntensity" << " err(%)" << endl;
11747  cout.width(25); cout << TurbIntensityOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)];
11748  cout.width(25); cout << TurbIntensityIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring +1)];
11749  cout.width(25); cout << abs((TurbIntensityIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring+1)] - TurbIntensityOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)])/TurbIntensityIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring+1)])*100.0;
11750  cout << endl;
11751  cout << endl;
11752  cout << " Outlet Turb2LamRatio " << " Inlet Turb2LamRatio" << " err(%)" << endl;
11753  cout.width(25); cout << Turb2LamViscRatioOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)];
11754  cout.width(25); cout << Turb2LamViscRatioIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring +1)];
11755  cout.width(25); cout << abs((Turb2LamViscRatioIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring+1)] - Turb2LamViscRatioOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)])/Turb2LamViscRatioIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring+1)])*100.0;
11756  }
11757  else{
11758  cout << " Outlet Nu Factor " << " Inlet Nu Factor" << " err(%)" << endl;
11759  cout.width(25); cout << NuFactorOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)];
11760  cout.width(25); cout << NuFactorIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring +1)];
11761  cout.width(25); cout << abs((NuFactorIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring+1)] - NuFactorOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)])/NuFactorIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring+1)])*100.0;
11762  }
11763  }
11764  cout << endl;
11765  cout << endl << "-------------------------------------------------------------------------" << endl;
11766  cout << endl;
11767  }
11768 
11769  }
11770  if(nZone > 1){
11771  /*--- Stage Performance ---*/
11772  for(iStage = 0; iStage < nStages; iStage++ ){
11773  cout << endl << "----------------------------- Stage " << iStage + 1 << " -----------------------------------" << endl;
11774  inMarker_Tag = config->GetMarker_TurboPerf_BoundIn(iStage*2);
11775  outMarker_Tag = config->GetMarker_TurboPerf_BoundOut(iStage*2+1);
11776  cout << "Stage performance between boundaries " << inMarker_Tag << " and "<< outMarker_Tag << " : "<<endl;
11777  cout << endl;
11778  cout << " Total-Total Eff.(%)" << " Total-Static Eff.(%)" << " Entropy Generation(%)" << endl;
11779  cout.width(25); cout << TotalTotalEfficiency[nBladesRow + iStage][nSpanWiseSections]*100.0;
11780  cout.width(25); cout << TotalStaticEfficiency[nBladesRow + iStage][nSpanWiseSections]*100.0;
11781  cout.width(25); cout << EntropyGen[nBladesRow + iStage][nSpanWiseSections]*100.0;
11782  cout << endl;
11783  cout << endl;
11784  cout << " Pressure Ratio " << " Outlet Is. Enthalpy" << " In-Out MassFlow Diff (%)" << endl;
11785  cout.width(25); cout << PressureRatio[nBladesRow + iStage][nSpanWiseSections];
11786  cout.width(25); cout << EnthalpyOutIs[nBladesRow + iStage][nSpanWiseSections]*config->GetEnergy_Ref();
11787  cout.width(25); cout << abs((MassFlowIn[nBladesRow + iStage][nSpanWiseSections] - MassFlowOut[nBladesRow + iStage][nSpanWiseSections])/MassFlowIn[nBladesRow + iStage][nSpanWiseSections])*100.0;
11788  }
11789  cout << endl;
11790  cout << endl << "-------------------------------------------------------------------------" << endl;
11791  cout << endl;
11792 
11793  /*--- Full Machine Performance ---*/
11794  // if(turbine)
11795  cout << endl << "---------------------------- Turbine ------------------------------------" << endl;
11796  inMarker_Tag = config->GetMarker_TurboPerf_BoundIn(0);
11797  outMarker_Tag = config->GetMarker_TurboPerf_BoundOut(nBladesRow-1);
11798  cout << "Turbine performance between boundaries " << inMarker_Tag << " and "<< outMarker_Tag << " : "<<endl;
11799  cout << endl;
11800  cout << " Total-Total Eff.(%)" << " Total-Static Eff.(%)" << " Entropy Generation(%)" << endl;
11801  cout.width(25); cout << TotalTotalEfficiency[nBladesRow + nStages][nSpanWiseSections]*100.0;
11802  cout.width(25); cout << TotalStaticEfficiency[nBladesRow + nStages][nSpanWiseSections]*100.0;
11803  cout.width(25); cout << EntropyGen[nBladesRow + nStages][nSpanWiseSections]*100.0;
11804  cout << endl;
11805  cout << endl;
11806  cout << " Pressure Ratio " << " Outlet Is. Enthalpy" << " In-Out MassFlow Diff (%)" << endl;
11807  cout.width(25); cout << PressureRatio[nBladesRow + nStages][nSpanWiseSections];
11808  cout.width(25); cout << EnthalpyOutIs[nBladesRow + nStages][nSpanWiseSections]*config->GetEnergy_Ref();;
11809  cout.width(25); cout << abs((MassFlowIn[nBladesRow + nStages][nSpanWiseSections] - MassFlowOut[nBladesRow + nStages][nSpanWiseSections])/MassFlowIn[nBladesRow + nStages][nSpanWiseSections])*100.0;
11810  cout << endl;
11811  cout << endl << "-------------------------------------------------------------------------" << endl;
11812  cout << endl;
11813  }
11814 
11815 }
11816 
11817 void COutputLegacy::SpecialOutput_Turbo(CSolver *****solver, CGeometry ****geometry, CConfig **config,
11818  unsigned short val_iZone, bool output) {
11819 
11820  string inMarker_Tag, outMarker_Tag, inMarkerTag_Mix;
11821  unsigned short nZone = config[val_iZone]->GetnZone();
11822 
11823  unsigned short iDim, iSpan;
11824 
11825  unsigned long iExtIter = config[val_iZone]->GetInnerIter();
11826  su2double* SpanWiseValuesIn, *SpanWiseValuesOut;
11827  ofstream myfile;
11828  string spanwise_performance_filename;
11829 
11830 
11831  /*--- Start of write file turboperformance spanwise ---*/
11832  if (rank == MASTER_NODE){
11833  SpanWiseValuesIn = geometry[val_iZone][INST_0][MESH_0]->GetSpanWiseValue(1);
11834  SpanWiseValuesOut = geometry[val_iZone][INST_0][MESH_0]->GetSpanWiseValue(2);
11835 
11836 
11837 
11838  /*--- Writing Span wise inflow thermodynamic quantities. ---*/
11839  spanwise_performance_filename = "TURBOMACHINERY/inflow_spanwise_thermodynamic_values.dat";
11840  char buffer[50];
11841  if (nZone > 1){
11842  unsigned short lastindex = spanwise_performance_filename.find_last_of(".");
11843  spanwise_performance_filename = spanwise_performance_filename.substr(0, lastindex);
11844  SPRINTF (buffer, "_%d.dat", SU2_TYPE::Int(val_iZone));
11845  spanwise_performance_filename.append(string(buffer));
11846  }
11847 
11848 
11849  myfile.open (spanwise_performance_filename.data(), ios::out | ios::trunc);
11850  myfile.setf(ios::scientific);
11851  myfile.precision(12);
11852 
11853  myfile << "TITLE = \"Inflow Spanwise Thermodynamic Values. iExtIter = " << iExtIter << " \"" << endl;
11854  myfile << "VARIABLES =" << endl;
11855 
11856  myfile.width(30); myfile << "\"SpanWise Value[m]\"";
11857  myfile.width(15); myfile << "\"iSpan\"";
11858  myfile.width(30); myfile << "\"Pressure[Pa]\"";
11859  myfile.width(30); myfile << "\"TotalPressure[Pa]\"";
11860  myfile.width(30); myfile << "\"Temperature[K]\"";
11861  myfile.width(30); myfile << "\"TotalTemperature[K]\"";
11862  myfile.width(30); myfile << "\"Enthalpy[J]\"";
11863  myfile.width(30); myfile << "\"TotalEnthalpy[J]\"";
11864  myfile.width(30); myfile << "\"Density[kg/m3]\"";
11865  myfile.width(30); myfile << "\"Entropy[J/K]\"";
11866  myfile.width(30); myfile << "\"TurbIntensity[-]\"";
11867  myfile.width(30); myfile << "\"Turb2LamViscRatio[-]\"";
11868  myfile.width(30); myfile << "\"NuFactor[-]\"";
11869  myfile << endl;
11870 
11871  for(iSpan = 0; iSpan < config[ZONE_0]->GetnSpan_iZones(val_iZone); iSpan++){
11872 
11873  myfile.width(30); myfile << SpanWiseValuesIn[iSpan];
11874  myfile.width(15); myfile << iSpan;
11875  myfile.width(30); myfile << PressureIn [val_iZone][iSpan]*config[ZONE_0]->GetPressure_Ref();
11876  myfile.width(30); myfile << TotalPressureIn [val_iZone][iSpan]*config[ZONE_0]->GetPressure_Ref();
11877  myfile.width(30); myfile << TemperatureIn [val_iZone][iSpan]*config[ZONE_0]->GetTemperature_Ref();
11878  myfile.width(30); myfile << TotalTemperatureIn [val_iZone][iSpan]*config[ZONE_0]->GetTemperature_Ref();
11879  myfile.width(30); myfile << EnthalpyIn [val_iZone][iSpan]*config[ZONE_0]->GetEnergy_Ref();
11880  myfile.width(30); myfile << TotalEnthalpyIn [val_iZone][iSpan]*config[ZONE_0]->GetEnergy_Ref();
11881  myfile.width(30); myfile << DensityIn [val_iZone][iSpan]*config[ZONE_0]->GetDensity_Ref();
11882  myfile.width(30); myfile << EntropyIn [val_iZone][iSpan]*config[ZONE_0]->GetEnergy_Ref()/config[ZONE_0]->GetTemperature_Ref();
11883  if(TurbIntensityIn[val_iZone][iSpan] > 1.0){
11884  myfile.width(30); myfile << TurbIntensityIn [val_iZone][config[ZONE_0]->GetnSpan_iZones(val_iZone)/2];
11885  }else{
11886  myfile.width(30); myfile << TurbIntensityIn [val_iZone][iSpan];
11887  }
11888  myfile.width(30); myfile << Turb2LamViscRatioIn [val_iZone][iSpan];
11889  myfile.width(30); myfile << NuFactorIn [val_iZone][iSpan];
11890  myfile << endl;
11891  }
11892 
11893  myfile.close();
11894 
11895  /*--- Writing Span wise outflow thermodynamic quantities. ---*/
11896  spanwise_performance_filename = "TURBOMACHINERY/outflow_spanwise_thermodynamic_values.dat";
11897  if (nZone > 1){
11898  unsigned short lastindex = spanwise_performance_filename.find_last_of(".");
11899  spanwise_performance_filename = spanwise_performance_filename.substr(0, lastindex);
11900  SPRINTF (buffer, "_%d.dat", SU2_TYPE::Int(val_iZone));
11901  spanwise_performance_filename.append(string(buffer));
11902  }
11903 
11904  myfile.open (spanwise_performance_filename.data(), ios::out | ios::trunc);
11905  myfile.setf(ios::scientific);
11906  myfile.precision(12);
11907 
11908  myfile << "TITLE = \"Outflow Span-wise Thermodynamic Values. iExtIter = " << iExtIter << " \"" << endl;
11909  myfile << "VARIABLES =" << endl;
11910 
11911  myfile.width(30); myfile << "\"SpanWise Value[m]\"";
11912  myfile.width(15); myfile << "\"iSpan\"";
11913  myfile.width(30); myfile << "\"Pressure[Pa]\"";
11914  myfile.width(30); myfile << "\"TotalPressure[Pa]\"";
11915  myfile.width(30); myfile << "\"Temperature[K]\"";
11916  myfile.width(30); myfile << "\"TotalTemperature[K]\"";
11917  myfile.width(30); myfile << "\"Enthalpy[J]\"";
11918  myfile.width(30); myfile << "\"TotalEnthalpy[J]\"";
11919  myfile.width(30); myfile << "\"Density[kg/m3]\"";
11920  myfile.width(30); myfile << "\"Entropy[J/K]\"";
11921  myfile.width(30); myfile << "\"TurbIntensity[-]\"";
11922  myfile.width(30); myfile << "\"Turb2LamViscRatio[-]\"";
11923  myfile.width(30); myfile << "\"NuFactor[-]\"";
11924  myfile << endl;
11925 
11926 
11927  for(iSpan = 0; iSpan < config[ZONE_0]->GetnSpan_iZones(val_iZone); iSpan++){
11928 
11929  myfile.width(30); myfile << SpanWiseValuesOut[iSpan];
11930  myfile.width(15); myfile << iSpan;
11931  myfile.width(30); myfile << PressureOut [val_iZone][iSpan]*config[ZONE_0]->GetPressure_Ref();
11932  myfile.width(30); myfile << TotalPressureOut [val_iZone][iSpan]*config[ZONE_0]->GetPressure_Ref();
11933  myfile.width(30); myfile << TemperatureOut [val_iZone][iSpan]*config[ZONE_0]->GetTemperature_Ref();
11934  myfile.width(30); myfile << TotalTemperatureOut [val_iZone][iSpan]*config[ZONE_0]->GetTemperature_Ref();
11935  myfile.width(30); myfile << EnthalpyOut [val_iZone][iSpan]*config[ZONE_0]->GetEnergy_Ref();
11936  myfile.width(30); myfile << TotalEnthalpyOut [val_iZone][iSpan]*config[ZONE_0]->GetEnergy_Ref();
11937  myfile.width(30); myfile << DensityOut [val_iZone][iSpan]*config[ZONE_0]->GetDensity_Ref();
11938  myfile.width(30); myfile << EntropyOut [val_iZone][iSpan]*config[ZONE_0]->GetEnergy_Ref()/config[ZONE_0]->GetTemperature_Ref();
11939  if(TurbIntensityOut[val_iZone][iSpan] > 1.0){
11940  myfile.width(30); myfile << TurbIntensityOut [val_iZone][config[ZONE_0]->GetnSpan_iZones(val_iZone)/2];
11941  }else{
11942  myfile.width(30); myfile << TurbIntensityOut [val_iZone][iSpan];
11943  }
11944  myfile.width(30); myfile << Turb2LamViscRatioOut [val_iZone][iSpan];
11945  myfile.width(30); myfile << NuFactorOut [val_iZone][iSpan];
11946  myfile << endl;
11947  }
11948 
11949  myfile.close();
11950 
11951  /*--- Writing Span wise inflow kinematic quantities. ---*/
11952  spanwise_performance_filename = "TURBOMACHINERY/inflow_spanwise_kinematic_values.dat";
11953  if (nZone > 1){
11954  unsigned short lastindex = spanwise_performance_filename.find_last_of(".");
11955  spanwise_performance_filename = spanwise_performance_filename.substr(0, lastindex);
11956  SPRINTF (buffer, "_%d.dat", SU2_TYPE::Int(val_iZone));
11957  spanwise_performance_filename.append(string(buffer));
11958  }
11959 
11960  myfile.open (spanwise_performance_filename.data(), ios::out | ios::trunc);
11961  myfile.setf(ios::scientific);
11962  myfile.precision(12);
11963 
11964  myfile << "TITLE = \"Inflow Span-wise Kinematic Values. iExtIter = " << iExtIter << " \"" << endl;
11965  myfile << "VARIABLES =" << endl;
11966 
11967  myfile.width(30); myfile << "\"SpanWise Value[m]\"";
11968  myfile.width(15); myfile << "\"iSpan\"";
11969  myfile.width(30); myfile << "\"Normal Mach[-]\"";
11970  myfile.width(30); myfile << "\"Tangential Mach[-]\"";
11971  myfile.width(30); myfile << "\"3rd Component Mach[-]\"";
11972  myfile.width(30); myfile << "\"Mach Module[-]\"";
11973  myfile.width(30); myfile << "\"Normal Velocity[m/s]\"";
11974  myfile.width(30); myfile << "\"Tangential Velocity[m/s]\"";
11975  myfile.width(30); myfile << "\"3rd Component Velocity[m/s]\"";
11976  myfile.width(30); myfile << "\"Velocity Module[m/s]\"";
11977  myfile.width(30); myfile << "\"Absolute Flow Angle[deg]\"";
11978  myfile.width(30); myfile << "\"Relative Flow Angle[deg]\"";
11979  myfile << endl;
11980 
11981 
11982  for(iSpan = 0; iSpan < config[ZONE_0]->GetnSpan_iZones(val_iZone); iSpan++){
11983 
11984  myfile.width(30); myfile << SpanWiseValuesIn[iSpan];
11985  myfile.width(15); myfile << iSpan;
11986  for (iDim = 0; iDim < 4; iDim++){
11987  myfile.width(30); myfile << MachIn [val_iZone][iSpan][iDim];
11988  }
11989  for (iDim = 0; iDim < 4; iDim++){
11990  myfile.width(30); myfile << TurboVelocityIn [val_iZone][iSpan][iDim]*config[ZONE_0]->GetVelocity_Ref();
11991  }
11992  if(AbsFlowAngleIn[val_iZone][iSpan] != AbsFlowAngleIn[val_iZone][iSpan]){
11993  myfile.width(30); myfile << "0.0000";
11994  }
11995  else{
11996  myfile.width(30); myfile << AbsFlowAngleIn [val_iZone][iSpan]*180.0/PI_NUMBER;
11997  }
11998  if(FlowAngleIn[val_iZone][iSpan] != FlowAngleIn[val_iZone][iSpan]){
11999  myfile.width(30); myfile << "0.0000";
12000  }
12001  else{
12002  myfile.width(30); myfile << FlowAngleIn [val_iZone][iSpan]*180.0/PI_NUMBER;
12003  }
12004  myfile << endl;
12005  }
12006 
12007  myfile.close();
12008 
12009  /*--- Writing Span wise outflow thermodynamic quantities. ---*/
12010  spanwise_performance_filename = "TURBOMACHINERY/outflow_spanwise_kinematic_values.dat";
12011  if (nZone > 1){
12012  unsigned short lastindex = spanwise_performance_filename.find_last_of(".");
12013  spanwise_performance_filename = spanwise_performance_filename.substr(0, lastindex);
12014  SPRINTF (buffer, "_%d.dat", SU2_TYPE::Int(val_iZone));
12015  spanwise_performance_filename.append(string(buffer));
12016  }
12017 
12018  myfile.open (spanwise_performance_filename.data(), ios::out | ios::trunc);
12019  myfile.setf(ios::scientific);
12020  myfile.precision(12);
12021 
12022  myfile << "TITLE = \"Outflow Span-wise Kinematic Values. iExtIter = " << iExtIter << " \"" << endl;
12023  myfile << "VARIABLES =" << endl;
12024 
12025  myfile.width(30); myfile << "\"SpanWise Value[m]\"";
12026  myfile.width(15); myfile << "\"iSpan\"";
12027  myfile.width(30); myfile << "\"Normal Mach[-]\"";
12028  myfile.width(30); myfile << "\"Tangential Mach[-]\"";
12029  myfile.width(30); myfile << "\"3rd Component Mach[-]\"";
12030  myfile.width(30); myfile << "\"Mach Module[-]\"";
12031  myfile.width(30); myfile << "\"Normal Velocity[m/s]\"";
12032  myfile.width(30); myfile << "\"Tangential Velocity[m/s]\"";
12033  myfile.width(30); myfile << "\"3rd Component Velocity[m/s]\"";
12034  myfile.width(30); myfile << "\"Velocity Module[m/s]\"";
12035  myfile.width(30); myfile << "\"Absolute Flow Angle[deg]\"";
12036  myfile.width(30); myfile << "\"Relative Flow Angle[deg]\"";
12037  myfile << endl;
12038 
12039 
12040  for(iSpan = 0; iSpan < config[ZONE_0]->GetnSpan_iZones(val_iZone); iSpan++){
12041 
12042  myfile.width(30); myfile << SpanWiseValuesOut[iSpan];
12043  myfile.width(15); myfile << iSpan;
12044  for (iDim = 0; iDim < 4; iDim++){
12045  myfile.width(30); myfile << MachOut [val_iZone][iSpan][iDim];
12046  }
12047  for (iDim = 0; iDim < 4; iDim++){
12048  myfile.width(30); myfile << TurboVelocityOut [val_iZone][iSpan][iDim]*config[ZONE_0]->GetVelocity_Ref();
12049  }
12050  if(AbsFlowAngleOut[val_iZone][iSpan] != AbsFlowAngleOut[val_iZone][iSpan]){
12051  myfile.width(30); myfile << "0.0000";
12052  }
12053  else{
12054  myfile.width(30); myfile << AbsFlowAngleOut [val_iZone][iSpan]*180.0/PI_NUMBER;
12055  }
12056  if(FlowAngleOut[val_iZone][iSpan] != FlowAngleOut[val_iZone][iSpan]){
12057  myfile.width(30); myfile << "0.0000";
12058  }
12059  else{
12060  myfile.width(30); myfile << FlowAngleOut [val_iZone][iSpan]*180.0/PI_NUMBER;
12061  }
12062  myfile << endl;
12063  }
12064 
12065  myfile.close();
12066 
12067  }
12068 }
12069 
12070 void COutputLegacy::SpecialOutput_HarmonicBalance(CSolver *****solver, CGeometry ****geometry, CConfig **config, unsigned short iInst, unsigned short val_nInst, bool output) {
12071 
12072  /*--- Write file with flow quantities for harmonic balance HB ---*/
12073  ofstream HB_output_file;
12074  ofstream mean_HB_file;
12075 
12076  /*--- MPI Send/Recv buffers ---*/
12077  su2double *sbuf_var = NULL, *rbuf_var = NULL;
12078 
12079  /*--- Other variables ---*/
12080  unsigned short iVar, kInst;
12081  unsigned short nVar_output = 5;
12082  unsigned long current_iter = config[ZONE_0]->GetInnerIter();
12083 
12084  /*--- Allocate memory for send buffer ---*/
12085  sbuf_var = new su2double[nVar_output];
12086 
12087  su2double *averages = new su2double[nVar_output];
12088  for (iVar = 0; iVar < nVar_output; iVar++)
12089  averages[iVar] = 0;
12090 
12091  /*--- Allocate memory for receive buffer ---*/
12092  if (rank == MASTER_NODE) {
12093  rbuf_var = new su2double[nVar_output];
12094 
12095  HB_output_file.precision(15);
12096  HB_output_file.open("HB_output.csv", ios::out);
12097  HB_output_file << "\"time_instance\",\"CL\",\"CD\",\"CMx\",\"CMy\",\"CMz\"" << endl;
12098 
12099  mean_HB_file.precision(15);
12100  if (current_iter == 0 && iInst == 1) {
12101  mean_HB_file.open("history_HB.plt", ios::trunc);
12102  mean_HB_file << "TITLE = \"SU2 HARMONIC BALANCE SIMULATION\"" << endl;
12103  mean_HB_file << "VARIABLES = \"Iteration\",\"CL\",\"CD\",\"CMx\",\"CMy\",\"CMz\",\"CT\",\"CQ\",\"CMerit\"" << endl;
12104  mean_HB_file << "ZONE T= \"Average Convergence History\"" << endl;
12105  }
12106  else
12107  mean_HB_file.open("history_HB.plt", ios::out | ios::app);
12108  }
12109 
12110  if (rank == MASTER_NODE) {
12111 
12112  /*--- Run through the zones, collecting the output variables
12113  N.B. Summing across processors within a given zone is being done
12114  elsewhere. ---*/
12115  for (kInst = 0; kInst < val_nInst; kInst++) {
12116 
12117  /*--- Flow solution coefficients (parallel) ---*/
12118  sbuf_var[0] = solver[ZONE_0][kInst][MESH_0][FLOW_SOL]->GetTotal_CL();
12119  sbuf_var[1] = solver[ZONE_0][kInst][INST_0][FLOW_SOL]->GetTotal_CD();
12120  sbuf_var[2] = solver[ZONE_0][kInst][INST_0][FLOW_SOL]->GetTotal_CMx();
12121  sbuf_var[3] = solver[ZONE_0][kInst][INST_0][FLOW_SOL]->GetTotal_CMy();
12122  sbuf_var[4] = solver[ZONE_0][kInst][INST_0][FLOW_SOL]->GetTotal_CMz();
12123 
12124  for (iVar = 0; iVar < nVar_output; iVar++) {
12125  rbuf_var[iVar] = sbuf_var[iVar];
12126  }
12127 
12128  HB_output_file << kInst << ", ";
12129  for (iVar = 0; iVar < nVar_output; iVar++)
12130  HB_output_file << rbuf_var[iVar] << ", ";
12131  HB_output_file << endl;
12132 
12133  /*--- Increment the total contributions from each zone, dividing by nZone as you go ---*/
12134  for (iVar = 0; iVar < nVar_output; iVar++) {
12135  averages[iVar] += (1.0/su2double(val_nInst))*rbuf_var[iVar];
12136  }
12137  }
12138  }
12139 
12140  if (rank == MASTER_NODE && iInst == INST_0) {
12141 
12142  mean_HB_file << current_iter << ", ";
12143  for (iVar = 0; iVar < nVar_output; iVar++) {
12144  mean_HB_file << averages[iVar];
12145  if (iVar < nVar_output-1)
12146  mean_HB_file << ", ";
12147  }
12148  mean_HB_file << endl;
12149  }
12150 
12151  if (rank == MASTER_NODE) {
12152  HB_output_file.close();
12153  mean_HB_file.close();
12154  delete [] rbuf_var;
12155  }
12156 
12157  delete [] sbuf_var;
12158  delete [] averages;
12159 }
12160 
12161 void COutputLegacy::SetSpecial_Output(CSolver *****solver_container,
12162  CGeometry ****geometry,
12163  CConfig **config,
12164  unsigned long iExtIter,
12165  unsigned short val_nZone) {
12166 
12167  bool special_output = false;
12168  unsigned short iZone;
12169 
12170  for (iZone = 0; iZone < val_nZone; iZone++){
12171 
12172  special_output = config[iZone]->GetSpecial_Output();
12173 
12174  /*--- Output a file with the forces breakdown. ---*/
12175  if (config[iZone]->GetWrt_ForcesBreakdown())
12176  SpecialOutput_ForcesBreakdown(solver_container, geometry, config, iZone, special_output);
12177 
12178  }
12179 
12180 }
12181 
12183  CGeometry ****geometry,
12184  CConfig **config,
12185  unsigned long iExtIter,
12186  unsigned short val_nZone) {
12187 
12188  unsigned short iZone, iVar, iInst;
12189  unsigned long iPoint;
12190  unsigned short nInst = 1;
12191  bool compressible = true;
12192 
12193  for (iZone = 0; iZone < val_nZone; iZone++) {
12194 
12195  /*--- Bool to distinguish between the FVM and FEM solvers. ---*/
12196  unsigned short KindSolver = config[iZone]->GetKind_Solver();
12197  bool fem_solver = ((KindSolver == FEM_EULER) ||
12198  (KindSolver == FEM_NAVIER_STOKES) ||
12199  (KindSolver == FEM_RANS) ||
12200  (KindSolver == FEM_LES));
12201 
12202  /*--- Get the file output format ---*/
12203 
12204  unsigned short FileFormat = config[iZone]->GetTabular_FileFormat();
12205  nInst = config[iZone]->GetnTimeInstances();
12206 
12207  for (iInst = 0; iInst < nInst; iInst++){
12208 
12209  bool cont_adj = config[iZone]->GetContinuous_Adjoint();
12210  bool disc_adj = config[iZone]->GetDiscrete_Adjoint();
12211 
12212  /*--- Flags identifying the types of files to be written. ---*/
12213  /*--- For now, we are disabling the parallel writers for Tecplot
12214  ASCII until we have parallel versions of all file formats
12215  available. SU2_SOL will remain intact for writing files
12216  until this capability is completed. ---*/
12217 
12218  bool Wrt_Vol = config[iZone]->GetWrt_Vol_Sol();
12219  bool Wrt_Srf = config[iZone]->GetWrt_Srf_Sol();
12220  bool Wrt_Csv = config[iZone]->GetWrt_Csv_Sol();
12221 
12222 #ifdef HAVE_MPI
12223  /*--- Do not merge the connectivity or write the visualization files
12224  if we are running in parallel, unless we are using ParaView binary.
12225  Force the use of SU2_SOL to merge and write the viz. files in this
12226  case to save overhead. ---*/
12227 
12228  if ((size > SINGLE_NODE) && (FileFormat != PARAVIEW_BINARY)) {
12229  Wrt_Vol = false;
12230  Wrt_Srf = false;
12231  }
12232 #endif
12233 
12234  /*--- Check for compressible/incompressible flow problems. ---*/
12235 
12236  compressible = (config[iZone]->GetKind_Regime() == COMPRESSIBLE);
12237 
12238  /*--- First, prepare the offsets needed throughout below. ---*/
12239 
12240  PrepareOffsets(config[iZone], geometry[iZone][iInst][MESH_0]);
12241 
12242  /*--- Write out CSV files in parallel for flow and adjoint. ---*/
12243 
12244  if (rank == MASTER_NODE) cout << endl << "Writing comma-separated values (CSV) surface files." << endl;
12245 
12246  switch (config[iZone]->GetKind_Solver()) {
12247  case EULER : case NAVIER_STOKES : case RANS :
12248  case INC_EULER : case INC_NAVIER_STOKES : case INC_RANS :
12249  if (Wrt_Csv) SetSurfaceCSV_Flow(config[iZone], geometry[iZone][iInst][MESH_0],
12250  solver_container[iZone][iInst][MESH_0][FLOW_SOL], iExtIter, iZone, iInst);
12251  break;
12252  case ADJ_EULER : case ADJ_NAVIER_STOKES : case ADJ_RANS :
12255  if (Wrt_Csv) SetSurfaceCSV_Adjoint(config[iZone], geometry[iZone][iInst][MESH_0],
12256  solver_container[iZone][iInst][MESH_0][ADJFLOW_SOL],
12257  solver_container[iZone][iInst][MESH_0][FLOW_SOL], iExtIter, iZone, iInst);
12258  break;
12259  default: break;
12260  }
12261 
12262  /*--- This switch statement will become a call to a virtual function
12263  defined within each of the "physics" output child classes that loads
12264  the local data for that particular problem alone. ---*/
12265 
12266  if (rank == MASTER_NODE)
12267  cout << "Loading solution output data locally on each rank." << endl;
12268 
12269  switch (config[iZone]->GetKind_Solver()) {
12270  case EULER : case NAVIER_STOKES : case RANS :
12271  case INC_EULER : case INC_NAVIER_STOKES : case INC_RANS :
12272  if (compressible)
12273  LoadLocalData_Flow(config[iZone], geometry[iZone][iInst][MESH_0], solver_container[iZone][iInst][MESH_0], iZone);
12274  else
12275  LoadLocalData_IncFlow(config[iZone], geometry[iZone][iInst][MESH_0], solver_container[iZone][iInst][MESH_0], iZone);
12276  break;
12277  case ADJ_EULER : case ADJ_NAVIER_STOKES : case ADJ_RANS :
12280  LoadLocalData_AdjFlow(config[iZone], geometry[iZone][iInst][MESH_0], solver_container[iZone][iInst][MESH_0], iZone);
12281  break;
12282  case FEM_ELASTICITY: case DISC_ADJ_FEM:
12283  LoadLocalData_Elasticity(config[iZone], geometry[iZone][iInst][MESH_0], solver_container[iZone][iInst][MESH_0], iZone);
12284  break;
12285  case HEAT_EQUATION_FVM:
12286  LoadLocalData_Base(config[iZone], geometry[iZone][iInst][MESH_0], solver_container[iZone][iInst][MESH_0], iZone);
12287  break;
12288  case FEM_EULER: case FEM_NAVIER_STOKES: case FEM_RANS: case FEM_LES:
12289  LoadLocalData_FEM(config[iZone], geometry[iZone][iInst][MESH_0], solver_container[iZone][iInst][MESH_0], iZone);
12290  default: break;
12291  }
12292 
12293  /*--- Store the solution to be used on the final iteration with cte. lift mode. ---*/
12294 
12295  if ((!cont_adj) && (!disc_adj) && (config[iZone]->GetFixed_CL_Mode()) &&
12296  (solver_container[iZone][iInst][MESH_0][FLOW_SOL]->GetStart_AoA_FD()) &&
12297  iExtIter == solver_container[iZone][iInst][MESH_0][FLOW_SOL]->GetIter_Update_AoA()) {
12298  //(config[iZone]->GetnExtIter()-config[iZone]->GetIter_dCL_dAlpha() -1 == iExtIter)) {
12299 
12300  if (rank == MASTER_NODE)
12301  cout << "Storing solution output data locally on each rank (cte. CL mode)." << endl;
12302 
12303  Local_Data_Copy = new su2double*[geometry[iZone][iInst][MESH_0]->GetnPoint()];
12304  for (iPoint = 0; iPoint < geometry[iZone][iInst][MESH_0]->GetnPoint(); iPoint++) {
12305  Local_Data_Copy[iPoint] = new su2double[nVar_Par];
12306  }
12307 
12308  for (iPoint = 0; iPoint < geometry[iZone][iInst][MESH_0]->GetnPoint(); iPoint++) {
12309  for (iVar = 0; iVar < nVar_Par; iVar++) {
12310  Local_Data_Copy[iPoint][iVar] = Local_Data[iPoint][iVar];
12311  }
12312  }
12313 
12314  }
12315 
12316  /*--- Recover the solution to be used on the final iteration with cte. lift mode. ---*/
12317 
12318  if ((!cont_adj) && (!disc_adj) && (config[iZone]->GetFixed_CL_Mode()) &&
12319  (solver_container[iZone][iInst][MESH_0][FLOW_SOL]->GetEnd_AoA_FD()) &&
12320  //(iExtIter - solver_container[iZone][iInst][MESH_0][FLOW_SOL]->GetIter_Update_AoA() == config[iZone]->GetIter_dCL_dAlpha()) &&
12321  (Local_Data_Copy != NULL)) {
12322 
12323  if (rank == MASTER_NODE)
12324  cout << "Recovering solution output data locally on each rank (cte. CL mode)." << endl;
12325 
12326  for (iPoint = 0; iPoint < geometry[iZone][iInst][MESH_0]->GetnPoint(); iPoint++) {
12327  for (iVar = 0; iVar < nVar_Par; iVar++) {
12328  Local_Data[iPoint][iVar] = Local_Data_Copy[iPoint][iVar];
12329  }
12330  }
12331 
12332  for (iPoint = 0; iPoint < geometry[iZone][iInst][MESH_0]->GetnPoint(); iPoint++)
12333  delete [] Local_Data_Copy[iPoint];
12334  delete [] Local_Data_Copy;
12335 
12336  }
12337 
12338  /*--- After loading the data local to a processor, we perform a sorting,
12339  i.e., a linear partitioning of the data across all ranks in the communicator. ---*/
12340 
12341  if (rank == MASTER_NODE) cout << "Sorting output data across all ranks." << endl;
12342 
12343  if (fem_solver)
12344  SortOutputData_FEM(config[iZone], geometry[iZone][iInst][MESH_0]);
12345  else
12346  SortOutputData(config[iZone], geometry[iZone][iInst][MESH_0]);
12347 
12348  /*--- Write either a binary or ASCII restart file in parallel. ---*/
12349 
12350  if (config[iZone]->GetWrt_Binary_Restart()) {
12351  if (rank == MASTER_NODE) cout << "Writing binary SU2 native restart file." << endl;
12352  WriteRestart_Parallel_Binary(config[iZone], geometry[iZone][iInst][MESH_0], solver_container[iZone][iInst][MESH_0], iZone, iInst);
12353  } else {
12354  if (rank == MASTER_NODE) cout << "Writing ASCII SU2 native restart file." << endl;
12355  WriteRestart_Parallel_ASCII(config[iZone], geometry[iZone][iInst][MESH_0], solver_container[iZone][iInst][MESH_0], iZone, iInst);
12356  }
12357 
12358  /*--- Write a slice on a structured mesh if requested. ---*/
12359 
12360  if (config[iZone]->GetWrt_Slice()) {
12361  WriteCSV_Slice(config[iZone], geometry[iZone][iInst][MESH_0],
12362  solver_container[iZone][iInst][MESH_0][FLOW_SOL], iExtIter, iZone, 0);
12363  WriteCSV_Slice(config[iZone], geometry[iZone][iInst][MESH_0],
12364  solver_container[iZone][iInst][MESH_0][FLOW_SOL], iExtIter, iZone, 1);
12365  }
12366 
12367  /*--- Write the solution files if they are requested and we are executing
12368  with a single rank (all data on one proc and no comm. overhead). Once we
12369  have parallel binary versions of Tecplot / ParaView / CGNS / etc., we
12370  can allow the write of the viz. files as well. ---*/
12371 
12372  if (Wrt_Vol || Wrt_Srf) {
12373 
12374  /*--- First, sort all connectivity into linearly partitioned chunks of elements. ---*/
12375 
12376  if (rank == MASTER_NODE)
12377  cout << "Preparing element connectivity across all ranks." << endl;
12378 
12379  if (fem_solver)
12380  SortConnectivity_FEM(config[iZone], geometry[iZone][iInst][MESH_0], iZone);
12381  else
12382  SortConnectivity(config[iZone], geometry[iZone][iInst][MESH_0], iZone);
12383 
12384  /*--- Sort the surface data and renumber if for writing. ---*/
12385  if (Wrt_Srf){
12386  if (fem_solver)
12387  SortOutputData_Surface_FEM(config[iZone], geometry[iZone][iInst][MESH_0]);
12388  else
12389  SortOutputData_Surface(config[iZone], geometry[iZone][iInst][MESH_0]);
12390  }
12391  /*--- Write Tecplot/ParaView ASCII files for the volume and/or surface solutions. ---*/
12392 
12393  if (Wrt_Vol) {
12394 
12395  switch (FileFormat) {
12396 
12397  case TECPLOT:
12398 
12399  /*--- Write a Tecplot ASCII file ---*/
12400 
12401  if (rank == MASTER_NODE) cout << "Writing Tecplot ASCII file volume solution file." << endl;
12402 // WriteTecplotASCII_Parallel(config[iZone], geometry[iZone][iInst][MESH_0],
12403 // solver_container[iZone][iInst][MESH_0], iZone, val_nZone, iInst, nInst, false);
12404  break;
12405 
12406 
12407 
12408  case TECPLOT_BINARY:
12409 
12410  /*--- Write a Tecplot ASCII file instead for now in serial. ---*/
12411 
12412  if (rank == MASTER_NODE) cout << "Tecplot binary volume files not available in serial with SU2_CFD." << endl;
12413  if (rank == MASTER_NODE) cout << " Run SU2_SOL to generate Tecplot binary." << endl;
12414  if (rank == MASTER_NODE) cout << "Writing Tecplot ASCII file volume solution file instead." << endl;
12415 // WriteTecplotASCII_Parallel(config[iZone], geometry[iZone][iInst][MESH_0],
12416 // solver_container[iZone][iInst][MESH_0], iZone, val_nZone, iInst, nInst, false);
12417  break;
12418 
12419 
12420 
12421  case PARAVIEW:
12422 
12423  /*--- Write a Paraview ASCII file ---*/
12424 
12425  if (rank == MASTER_NODE) cout << "Writing Paraview ASCII volume solution file." << endl;
12426 // WriteParaViewASCII_Parallel(config[iZone], geometry[iZone][iInst][MESH_0],
12427 // solver_container[iZone][iInst][MESH_0], iZone, val_nZone, iInst, nInst, false);
12428  break;
12429 
12430  case PARAVIEW_BINARY:
12431 
12432  /*--- Write a Paraview binary file ---*/
12433 
12434  if (rank == MASTER_NODE) cout << "Writing Paraview binary volume solution file." << endl;
12435 // WriteParaViewBinary_Parallel(config[iZone], geometry[iZone][iInst][MESH_0],
12436 // solver_container[iZone][iInst][MESH_0], iZone, val_nZone, false);
12437  break;
12438 
12439  default:
12440  break;
12441  }
12442 
12443  }
12444 
12445  if (Wrt_Srf) {
12446 
12447  switch (FileFormat) {
12448 
12449  case TECPLOT:
12450 
12451  /*--- Write a Tecplot ASCII file ---*/
12452 
12453  if (rank == MASTER_NODE) cout << "Writing Tecplot ASCII file surface solution file." << endl;
12454 // WriteTecplotASCII_Parallel(config[iZone], geometry[iZone][iInst][MESH_0],
12455 // solver_container[iZone][iInst][MESH_0], iZone, val_nZone, iInst, nInst, true);
12456  break;
12457 
12458  case TECPLOT_BINARY:
12459 
12460  /*--- Write a Tecplot ASCII file instead for now in serial. ---*/
12461 
12462  if (rank == MASTER_NODE) cout << "Tecplot binary surface files not available in serial with SU2_CFD." << endl;
12463  if (rank == MASTER_NODE) cout << " Run SU2_SOL to generate Tecplot binary." << endl;
12464  if (rank == MASTER_NODE) cout << "Writing Tecplot ASCII file surface solution file instead." << endl;
12465 // WriteTecplotASCII_Parallel(config[iZone], geometry[iZone][iInst][MESH_0],
12466 // solver_container[iZone][iInst][MESH_0], iZone, val_nZone, iInst, nInst, true);
12467  break;
12468 
12469  case PARAVIEW:
12470 
12471  /*--- Write a Paraview ASCII file ---*/
12472 
12473  if (rank == MASTER_NODE) cout << "Writing Paraview ASCII surface solution file." << endl;
12474 // WriteParaViewASCII_Parallel(config[iZone], geometry[iZone][iInst][MESH_0],
12475 // solver_container[iZone][iInst][MESH_0], iZone, val_nZone, iInst, nInst, true);
12476  break;
12477 
12478  case PARAVIEW_BINARY:
12479 
12480  /*--- Write a Paraview binary file ---*/
12481 
12482  if (rank == MASTER_NODE) cout << "Writing Paraview binary surface solution file." << endl;
12483 // WriteParaViewBinary_Parallel(config[iZone], geometry[iZone][iInst][MESH_0],
12484 // solver_container[iZone][iInst][MESH_0], iZone, val_nZone, true);
12485  break;
12486 
12487 
12488  default:
12489  break;
12490  }
12491 
12492  }
12493 
12494  /*--- Clean up the connectivity data that was allocated for output. ---*/
12495 
12496  DeallocateConnectivity_Parallel(config[iZone], geometry[iZone][iInst][MESH_0], false);
12497  if (Wrt_Srf) DeallocateConnectivity_Parallel(config[iZone], geometry[iZone][iInst][MESH_0], true);
12498 
12499  /*--- Clean up the surface data that was only needed for output. ---*/
12500 
12501  if (Wrt_Srf) DeallocateSurfaceData_Parallel(config[iZone], geometry[iZone][iInst][MESH_0]);
12502 
12503  }
12504 
12505  /*--- Deallocate the nodal data needed for writing restarts. ---*/
12506 
12507  DeallocateData_Parallel(config[iZone], geometry[iZone][iInst][MESH_0]);
12508 
12509  /*--- Clear the variable names list. ---*/
12510 
12511  Variable_Names.clear();
12512 
12513  }
12514  }
12515 }
12516 
12517 void COutputLegacy::LoadLocalData_Flow(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone) {
12518 
12519  unsigned short iDim;
12520  unsigned short Kind_Solver = config->GetKind_Solver();
12521  unsigned short nDim = geometry->GetnDim();
12522 
12523  unsigned long iVar, jVar;
12524  unsigned long iPoint, jPoint, FirstIndex = NONE, SecondIndex = NONE, iMarker, iVertex;
12525  unsigned long nVar_First = 0, nVar_Second = 0, nVar_Consv_Par = 0;
12526 
12527  su2double RefArea = config->GetRefArea();
12528  su2double Gamma = config->GetGamma();
12529  su2double RefVel2;
12530  su2double Gas_Constant, Mach2Vel, Mach_Motion, RefDensity, RefPressure = 0.0, factor = 0.0;
12531  su2double *Aux_Frict_x = NULL, *Aux_Frict_y = NULL, *Aux_Frict_z = NULL, *Aux_Heat = NULL, *Aux_yPlus = NULL, *Aux_Buffet = NULL;
12532  su2double *Grid_Vel = NULL;
12533  su2double Q, Grad_Vel[3][3] = {{0.0, 0.0, 0.0},{0.0, 0.0, 0.0},{0.0, 0.0, 0.0}};
12534 
12535  bool transition = (config->GetKind_Trans_Model() == BC);
12536  bool dynamic_grid = config->GetDynamic_Grid();
12537  bool rotating_frame = config->GetRotating_Frame();
12538  bool Wrt_Halo = config->GetWrt_Halo(), isPeriodic;
12539 
12540  int *Local_Halo = NULL;
12541 
12542  stringstream varname;
12543 
12544  /*--- Set the non-dimensionalization for coefficients. ---*/
12545 
12546  if (dynamic_grid) {
12547  Gas_Constant = config->GetGas_ConstantND();
12548  Mach2Vel = sqrt(Gamma*Gas_Constant*config->GetTemperature_FreeStreamND());
12549  Mach_Motion = config->GetMach_Motion();
12550  RefVel2 = (Mach_Motion*Mach2Vel)*(Mach_Motion*Mach2Vel);
12551  }
12552  else {
12553  RefVel2 = 0.0;
12554  for (iDim = 0; iDim < nDim; iDim++)
12555  RefVel2 += solver[FLOW_SOL]->GetVelocity_Inf(iDim)*solver[FLOW_SOL]->GetVelocity_Inf(iDim);
12556  }
12557  RefDensity = solver[FLOW_SOL]->GetDensity_Inf();
12558  RefPressure = solver[FLOW_SOL]->GetPressure_Inf();
12559  factor = 1.0 / (0.5*RefDensity*RefArea*RefVel2);
12560 
12561  /*--- Use a switch statement to decide how many solver containers we have
12562  in this zone for output. ---*/
12563 
12564  switch (config->GetKind_Solver()) {
12565  case EULER : case NAVIER_STOKES: FirstIndex = FLOW_SOL; SecondIndex = NONE; break;
12566  case RANS : FirstIndex = FLOW_SOL; SecondIndex = TURB_SOL; break;
12567  default: SecondIndex = NONE; break;
12568  }
12569 
12570  nVar_First = solver[FirstIndex]->GetnVar();
12571  if (SecondIndex != NONE) nVar_Second = solver[SecondIndex]->GetnVar();
12572  nVar_Consv_Par = nVar_First + nVar_Second;
12573 
12574  /*--------------------------------------------------------------------------*/
12575  /*--- Step 1: Register the variables that will be output. To register a ---*/
12576  /*--- variable, two things are required. First, increment the ---*/
12577  /*--- counter for the number of variables (nVar_Par), which ---*/
12578  /*--- controls the size of the data structure allocation, i.e., ---*/
12579  /*--- the number of columns in an nPoint x nVar structure. ---*/
12580  /*--- Second, add a name for the variable to the vector that ---*/
12581  /*--- holds the string names. ---*/
12582  /*--------------------------------------------------------------------------*/
12583 
12584  /*--- All output files first need the grid coordinates. ---*/
12585 
12586  nVar_Par = 1; Variable_Names.push_back("x");
12587  nVar_Par += 1; Variable_Names.push_back("y");
12588  if (geometry->GetnDim() == 3) {
12589  nVar_Par += 1; Variable_Names.push_back("z");
12590  }
12591 
12592  /*--- At a mininum, the restarts and visualization files need the
12593  conservative variables, so these follow next. ---*/
12594 
12595  nVar_Par += nVar_Consv_Par;
12596 
12597  Variable_Names.push_back("Density");
12598  Variable_Names.push_back("Momentum_x");
12599  Variable_Names.push_back("Momentum_y");
12600  if (geometry->GetnDim() == 3) Variable_Names.push_back("Momentum_z");
12601  Variable_Names.push_back("Energy");
12602 
12603  if (SecondIndex != NONE) {
12604  if ((config->GetKind_Turb_Model() == SST) || (config->GetKind_Turb_Model() == SST_SUST)) {
12605  Variable_Names.push_back("TKE");
12606  Variable_Names.push_back("Omega");
12607  } else {
12608  /*--- S-A variants ---*/
12609  Variable_Names.push_back("Nu_Tilde");
12610  }
12611  }
12612 
12613  /*--- If requested, register the limiter and residuals for all of the
12614  equations in the current flow problem. ---*/
12615 
12616  /*--- Add the limiters ---*/
12617 
12618  if (config->GetWrt_Limiters()) {
12619  nVar_Par += nVar_Consv_Par;
12620 
12621  Variable_Names.push_back("Limiter_Density");
12622  Variable_Names.push_back("Limiter_Momentum_x");
12623  Variable_Names.push_back("Limiter_Momentum_y");
12624  if (geometry->GetnDim() == 3) Variable_Names.push_back("Limiter_Momentum_z");
12625  Variable_Names.push_back("Limiter_Energy");
12626 
12627  if (SecondIndex != NONE) {
12628  if ((config->GetKind_Turb_Model() == SST) || (config->GetKind_Turb_Model() == SST_SUST)) {
12629  Variable_Names.push_back("Limiter_TKE");
12630  Variable_Names.push_back("Limiter_Omega");
12631  } else {
12632  /*--- S-A variants ---*/
12633  Variable_Names.push_back("Limiter_Nu_Tilde");
12634  }
12635  }
12636  }
12637 
12638  /*--- Add the residuals ---*/
12639 
12640  if (config->GetWrt_Residuals()) {
12641  nVar_Par += nVar_Consv_Par;
12642 
12643  Variable_Names.push_back("Residual_Density");
12644  Variable_Names.push_back("Residual_Momentum_x");
12645  Variable_Names.push_back("Residual_Momentum_y");
12646  if (geometry->GetnDim() == 3) Variable_Names.push_back("Residual_Momentum_z");
12647  Variable_Names.push_back("Residual_Energy");
12648 
12649  if (SecondIndex != NONE) {
12650  if ((config->GetKind_Turb_Model() == SST) || (config->GetKind_Turb_Model() == SST_SUST)) {
12651  Variable_Names.push_back("Residual_TKE");
12652  Variable_Names.push_back("Residual_Omega");
12653  } else {
12654  /*--- S-A variants ---*/
12655  Variable_Names.push_back("Residual_Nu_Tilde");
12656  }
12657  }
12658  }
12659 
12660  /*--- Add the grid velocity. ---*/
12661 
12662  if (dynamic_grid) {
12663  if (geometry->GetnDim() == 2) nVar_Par += 2;
12664  else if (geometry->GetnDim() == 3) nVar_Par += 3;
12665 
12666  Variable_Names.push_back("Grid_Velocity_x");
12667  Variable_Names.push_back("Grid_Velocity_y");
12668  if (geometry->GetnDim() == 3) Variable_Names.push_back("Grid_Velocity_z");
12669  }
12670 
12671 
12672  /*--- Add Pressure, Temperature, Cp, Mach. ---*/
12673 
12674  nVar_Par += 1;
12675  Variable_Names.push_back("Pressure");
12676 
12677  nVar_Par += 2;
12678  Variable_Names.push_back("Temperature");
12679  Variable_Names.push_back("Mach");
12680 
12681  nVar_Par += 1;
12682  if ((config->GetTabular_FileFormat() == TAB_CSV)){
12683  Variable_Names.push_back("Pressure_Coefficient");
12684  } else {
12685  Variable_Names.push_back("C<sub>p</sub>");
12686  }
12687 
12688  /*--- Add Laminar Viscosity, Skin Friction, Heat Flux, & yPlus to the restart file ---*/
12689 
12690  if ((Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) {
12691  if ((config->GetTabular_FileFormat() == TAB_CSV)){
12692  nVar_Par += 1; Variable_Names.push_back("Laminar_Viscosity");
12693  nVar_Par += 2;
12694  Variable_Names.push_back("Skin_Friction_Coefficient_x");
12695  Variable_Names.push_back("Skin_Friction_Coefficient_y");
12696  if (geometry->GetnDim() == 3) {
12697  nVar_Par += 1; Variable_Names.push_back("Skin_Friction_Coefficient_z");
12698  }
12699  nVar_Par += 1;
12700  Variable_Names.push_back("Heat_Flux");
12701  } else {
12702  nVar_Par += 1; Variable_Names.push_back("<greek>m</greek>");
12703  nVar_Par += 2;
12704  Variable_Names.push_back("C<sub>f</sub>_x");
12705  Variable_Names.push_back("C<sub>f</sub>_y");
12706  if (geometry->GetnDim() == 3) {
12707  nVar_Par += 1; Variable_Names.push_back("C<sub>f</sub>_z");
12708  }
12709  if (config->GetBuffet_Monitoring() || config->GetKind_ObjFunc() == BUFFET_SENSOR){
12710  Variable_Names.push_back("Buffet_Sensor");
12711  nVar_Par += 1;
12712  }
12713  nVar_Par += 1;
12714  Variable_Names.push_back("h");
12715  }
12716  }
12717 
12718  /*--- Add Eddy Viscosity. ---*/
12719 
12720  if (Kind_Solver == RANS) {
12721  nVar_Par += 2;
12722  if ((config->GetTabular_FileFormat() == TAB_CSV)){
12723  Variable_Names.push_back("Y_Plus");
12724  Variable_Names.push_back("Eddy_Viscosity");
12725  } else {
12726  Variable_Names.push_back("y<sup>+</sup>");
12727  Variable_Names.push_back("<greek>m</greek><sub>t</sub>");
12728  }
12729  }
12730 
12731  /*--- Add the distance to the nearest sharp edge if requested. ---*/
12732 
12733  if (config->GetWrt_SharpEdges()) {
12734  nVar_Par += 1;
12735  Variable_Names.push_back("Sharp_Edge_Dist");
12736  }
12737 
12738  /*--- Add the intermittency for the BC trans. model. ---*/
12739 
12740  if (transition) {
12741  nVar_Par += 1;
12742  if ((config->GetTabular_FileFormat() == TAB_CSV)){
12743  Variable_Names.push_back("gamma_BC");
12744  } else {
12745  Variable_Names.push_back("<greek>g</greek><sub>BC</sub>");
12746  }
12747  }
12748 
12749  if (config->GetKind_HybridRANSLES()!=NO_HYBRIDRANSLES){
12750  nVar_Par +=1;
12751  Variable_Names.push_back("DES_LengthScale");
12752  nVar_Par +=1;
12753  Variable_Names.push_back("Wall_Distance");
12754  }
12755 
12756  if (config->GetKind_RoeLowDiss() != NO_ROELOWDISS){
12757  nVar_Par +=1;
12758  Variable_Names.push_back("Roe_Dissipation");
12759  }
12760 
12761  if (solver[FLOW_SOL]->VerificationSolution) {
12762  if (solver[FLOW_SOL]->VerificationSolution->ExactSolutionKnown()) {
12763  nVar_Par += 2*nVar_Consv_Par;
12764  Variable_Names.push_back("Verification_Density");
12765  Variable_Names.push_back("Verification_Momentum_x");
12766  Variable_Names.push_back("Verification_Momentum_y");
12767  if (geometry->GetnDim() == 3) Variable_Names.push_back("Verification_Momentum_z");
12768  Variable_Names.push_back("Verification_Energy");
12769  Variable_Names.push_back("Error_Density");
12770  Variable_Names.push_back("Error_Momentum_x");
12771  Variable_Names.push_back("Error_Momentum_y");
12772  if (geometry->GetnDim() == 3) Variable_Names.push_back("Error_Momentum_z");
12773  Variable_Names.push_back("Error_Energy");
12774  }
12775  }
12776 
12777  /*--- New variables get registered here before the end of the loop. ---*/
12778 
12779  if ((Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) {
12780  nVar_Par += 2;
12781  Variable_Names.push_back("Vorticity_x");
12782  Variable_Names.push_back("Vorticity_y");
12783  if (geometry->GetnDim() == 3) {
12784  nVar_Par += 1; Variable_Names.push_back("Vorticity_z");
12785  }
12786 
12787  if (geometry->GetnDim() == 3) {
12788  nVar_Par +=1;
12789  Variable_Names.push_back("Q_Criterion");
12790  }
12791 
12792  }
12793 
12794  if (rotating_frame) {
12795  nVar_Par += 2;
12796  Variable_Names.push_back("Relative_Velocity_x");
12797  Variable_Names.push_back("Relative_Velocity_y");
12798  if (geometry->GetnDim() == 3) {
12799  nVar_Par += 1; Variable_Names.push_back("Relative_Velocity_z");
12800  }
12801  }
12802 
12803  if (config->GetWrt_MeshQuality()) {
12804  nVar_Par +=1;
12805  Variable_Names.push_back("Orthogonality");
12806  nVar_Par +=1;
12807  Variable_Names.push_back("Aspect_Ratio");
12808  nVar_Par +=1;
12809  Variable_Names.push_back("Volume_Ratio");
12810  }
12811 
12812 
12813 
12814  /*--- Auxiliary vectors for variables defined on surfaces only. ---*/
12815 
12816  if ((Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) {
12817  Aux_Frict_x = new su2double[geometry->GetnPoint()];
12818  Aux_Frict_y = new su2double[geometry->GetnPoint()];
12819  Aux_Frict_z = new su2double[geometry->GetnPoint()];
12820  Aux_Heat = new su2double[geometry->GetnPoint()];
12821  Aux_yPlus = new su2double[geometry->GetnPoint()];
12822  Aux_Buffet = new su2double[geometry->GetnPoint()];
12823 
12824  /*--- First, loop through the mesh in order to find and store the
12825  value of the viscous coefficients at any surface nodes. They
12826  will be placed in an auxiliary vector and then communicated like
12827  all other volumetric variables. ---*/
12828 
12829  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
12830  Aux_Frict_x[iPoint] = 0.0;
12831  Aux_Frict_y[iPoint] = 0.0;
12832  Aux_Frict_z[iPoint] = 0.0;
12833  Aux_Heat[iPoint] = 0.0;
12834  Aux_yPlus[iPoint] = 0.0;
12835  Aux_Buffet[iPoint] = 0.0;
12836  }
12837  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
12838  if (config->GetMarker_All_Plotting(iMarker) == YES) {
12839  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
12840  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
12841  Aux_Frict_x[iPoint] = solver[FLOW_SOL]->GetCSkinFriction(iMarker, iVertex, 0);
12842  Aux_Frict_y[iPoint] = solver[FLOW_SOL]->GetCSkinFriction(iMarker, iVertex, 1);
12843  if (geometry->GetnDim() == 3) Aux_Frict_z[iPoint] = solver[FLOW_SOL]->GetCSkinFriction(iMarker, iVertex, 2);
12844  Aux_Heat[iPoint] = solver[FLOW_SOL]->GetHeatFlux(iMarker, iVertex);
12845  Aux_yPlus[iPoint] = solver[FLOW_SOL]->GetYPlus(iMarker, iVertex);
12846  if (config->GetBuffet_Monitoring() || config->GetKind_ObjFunc() == BUFFET_SENSOR) Aux_Buffet[iPoint] = solver[FLOW_SOL]->GetBuffetSensor(iMarker, iVertex);
12847  }
12848  }
12849  }
12850  }
12851 
12852  /*--- Allocate the local data structure now that we know how many
12853  variables are in the output. ---*/
12854 
12855  Local_Data = new su2double*[geometry->GetnPoint()];
12856  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
12857  Local_Data[iPoint] = new su2double[nVar_Par];
12858  }
12859 
12860  Local_Halo = new int[geometry->GetnPoint()];
12861  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
12862  Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain();
12863 
12864  /*--- Search all send/recv boundaries on this partition for any periodic
12865  nodes that were part of the original domain. We want to recover these
12866  for visualization purposes. ---*/
12867 
12868  if (!Wrt_Halo) {
12869  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
12870  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
12871 
12872  /*--- Checking for less than or equal to the rank, because there may
12873  be some periodic halo nodes that send info to the same rank. ---*/
12874 
12875  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
12876  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
12877  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
12878  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1));
12879  if (isPeriodic) Local_Halo[iPoint] = false;
12880  }
12881  }
12882  }
12883  }
12884 
12885  /*--------------------------------------------------------------------------*/
12886  /*--- Step 2: Loop over all grid nodes and load up the desired data for ---*/
12887  /*--- the restart and vizualization files. Note that we need to ---*/
12888  /*--- increment the iVar variable after each variable load. ---*/
12889  /*--- The idea is that we're filling up the columns of field ---*/
12890  /*--- data for each iPoint (row) of the data structure. ---*/
12891  /*--- This data will then be sorted, communicated, and written ---*/
12892  /*--- to files automatically after this routine. Note that the ---*/
12893  /*--- ordering of the data loading MUST match the order of the ---*/
12894  /*--- variable registration above for the files to be correct. ---*/
12895  /*--------------------------------------------------------------------------*/
12896 
12897  jPoint = 0;
12898 
12899  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
12900 
12901  /*--- Check for halos & write only if requested ---*/
12902 
12903  if (!Local_Halo[iPoint] || Wrt_Halo) {
12904 
12905  /*--- Restart the column index with each new point. ---*/
12906 
12907  iVar = 0;
12908 
12909  /*--- Load the grid node coordinate values. ---*/
12910 
12911  for (iDim = 0; iDim < geometry->GetnDim(); iDim++) {
12912  Local_Data[jPoint][iVar] = geometry->node[iPoint]->GetCoord(iDim);
12913  if (config->GetSystemMeasurements() == US)
12914  Local_Data[jPoint][iVar] *= 12.0;
12915  iVar++;
12916  }
12917 
12918  /*--- Load the conservative variable states for the mean flow variables. ---*/
12919 
12920  for (jVar = 0; jVar < nVar_First; jVar++) {
12921  Local_Data[jPoint][iVar] = solver[FirstIndex]->GetNodes()->GetSolution(iPoint, jVar);
12922  iVar++;
12923  }
12924 
12925  /*--- If this is RANS, i.e., the second solver container is not empty,
12926  then load data for the conservative turbulence variables. ---*/
12927 
12928  if (SecondIndex != NONE) {
12929  for (jVar = 0; jVar < nVar_Second; jVar++) {
12930  Local_Data[jPoint][iVar] = solver[SecondIndex]->GetNodes()->GetSolution(iPoint, jVar);
12931  iVar++;
12932  }
12933  }
12934 
12935  /*--- If limiters and/or residuals are requested. ---*/
12936 
12937  /*--- Limiters ---*/
12938  if (config->GetWrt_Limiters()) {
12939  /*--- Mean Flow Limiters ---*/
12940  for (jVar = 0; jVar < nVar_First; jVar++) {
12941  Local_Data[jPoint][iVar] = solver[FirstIndex]->GetNodes()->GetLimiter_Primitive(iPoint, jVar);
12942  iVar++;
12943  }
12944  /*--- RANS Limiters ---*/
12945  if (SecondIndex != NONE) {
12946  for (jVar = 0; jVar < nVar_Second; jVar++) {
12947  Local_Data[jPoint][iVar] = solver[SecondIndex]->GetNodes()->GetLimiter_Primitive(iPoint, jVar);
12948  iVar++;
12949  }
12950  }
12951  }
12952 
12953  /*--- Residuals ---*/
12954  if (config->GetWrt_Residuals()) {
12955  /*--- Mean Flow Residuals ---*/
12956  for (jVar = 0; jVar < nVar_First; jVar++) {
12957  Local_Data[jPoint][iVar] = solver[FirstIndex]->LinSysRes.GetBlock(iPoint, jVar);
12958  iVar++;
12959  }
12960  /*--- RANS Residuals ---*/
12961  if (SecondIndex != NONE) {
12962  for (jVar = 0; jVar < nVar_Second; jVar++) {
12963  Local_Data[jPoint][iVar] = solver[SecondIndex]->LinSysRes.GetBlock(iPoint, jVar);
12964  iVar++;
12965  }
12966  }
12967  }
12968 
12969 
12970 
12971  /*--- Load buffers with the three grid velocity components. ---*/
12972 
12973  if (dynamic_grid) {
12974  Grid_Vel = geometry->node[iPoint]->GetGridVel();
12975  Local_Data[jPoint][iVar] = Grid_Vel[0]; iVar++;
12976  Local_Data[jPoint][iVar] = Grid_Vel[1]; iVar++;
12977  if (geometry->GetnDim() == 3) {
12978  Local_Data[jPoint][iVar] = Grid_Vel[2];
12979  iVar++;
12980  }
12981  }
12982 
12983  /*--- Load data for the pressure, temperature, Cp, and Mach variables. ---*/
12984 
12985  Local_Data[jPoint][iVar] = solver[FLOW_SOL]->GetNodes()->GetPressure(iPoint); iVar++;
12986  Local_Data[jPoint][iVar] = solver[FLOW_SOL]->GetNodes()->GetTemperature(iPoint); iVar++;
12987  Local_Data[jPoint][iVar] = sqrt(solver[FLOW_SOL]->GetNodes()->GetVelocity2(iPoint))/solver[FLOW_SOL]->GetNodes()->GetSoundSpeed(iPoint); iVar++;
12988  Local_Data[jPoint][iVar] = (solver[FLOW_SOL]->GetNodes()->GetPressure(iPoint) - RefPressure)*factor*RefArea; iVar++;
12989 
12990  if ((Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) {
12991 
12992  /*--- Load data for the laminar viscosity. ---*/
12993 
12994  Local_Data[jPoint][iVar] = solver[FLOW_SOL]->GetNodes()->GetLaminarViscosity(iPoint); iVar++;
12995 
12996  /*--- Load data for the skin friction, heat flux, buffet, and y-plus. ---*/
12997 
12998  Local_Data[jPoint][iVar] = Aux_Frict_x[iPoint]; iVar++;
12999  Local_Data[jPoint][iVar] = Aux_Frict_y[iPoint]; iVar++;
13000  if (geometry->GetnDim() == 3) {
13001  Local_Data[jPoint][iVar] = Aux_Frict_z[iPoint];
13002  iVar++;
13003  }
13004  if (config->GetBuffet_Monitoring() || config->GetKind_ObjFunc() == BUFFET_SENSOR) {
13005  Local_Data[jPoint][iVar] = Aux_Buffet[iPoint];
13006  iVar++;
13007  }
13008  Local_Data[jPoint][iVar] = Aux_Heat[iPoint]; iVar++;
13009 
13010  }
13011 
13012  /*--- Load data for the Eddy viscosity for RANS. ---*/
13013 
13014  if (Kind_Solver == RANS) {
13015  Local_Data[jPoint][iVar] = Aux_yPlus[iPoint]; iVar++;
13016  Local_Data[jPoint][iVar] = solver[FLOW_SOL]->GetNodes()->GetEddyViscosity(iPoint); iVar++;
13017  }
13018 
13019  /*--- Load data for the distance to the nearest sharp edge. ---*/
13020 
13021  if (config->GetWrt_SharpEdges()) {
13022  Local_Data[jPoint][iVar] = geometry->node[iPoint]->GetSharpEdge_Distance(); iVar++;
13023  }
13024 
13025  /*--- Load data for the intermittency of the BC trans. model. ---*/
13026 
13027  if (transition) {
13028  Local_Data[jPoint][iVar] = solver[TURB_SOL]->GetNodes()->GetGammaBC(iPoint); iVar++;
13029  }
13030 
13031  if (config->GetKind_HybridRANSLES()!=NO_HYBRIDRANSLES){
13032  Local_Data[jPoint][iVar] = solver[FLOW_SOL]->GetNodes()->GetDES_LengthScale(iPoint); iVar++;
13033  Local_Data[jPoint][iVar] = geometry->node[iPoint]->GetWall_Distance(); iVar++;
13034  }
13035 
13036  if (config->GetKind_RoeLowDiss() != NO_ROELOWDISS){
13037  Local_Data[jPoint][iVar] = solver[FLOW_SOL]->GetNodes()->GetRoe_Dissipation(iPoint); iVar++;
13038  }
13039 
13040  if (solver[FLOW_SOL]->VerificationSolution) {
13041  if (solver[FLOW_SOL]->VerificationSolution->ExactSolutionKnown()) {
13042 
13043  /*--- Get the physical time if necessary. ---*/
13044  su2double time = 0.0;
13045  if (config->GetTime_Marching()) time = config->GetPhysicalTime();
13046 
13047  /* Set the pointers to the coordinates and solution of this DOF. */
13048  const su2double *coor = geometry->node[iPoint]->GetCoord();
13049  su2double *solDOF = solver[FLOW_SOL]->GetNodes()->GetSolution(iPoint);
13050  su2double mmsSol[5] = {0.0,0.0,0.0,0.0,0.0};
13051  su2double error[5] = {0.0,0.0,0.0,0.0,0.0};
13052 
13053  /* Get the verification solution. */
13054  solver[FLOW_SOL]->VerificationSolution->GetSolution(coor, time, mmsSol);
13055  for (jVar = 0; jVar < nVar_First; jVar++) {
13056  Local_Data[jPoint][iVar] = mmsSol[jVar];
13057  iVar++;
13058  }
13059 
13060  /* Get local error from the verification solution class. */
13061  solver[FLOW_SOL]->VerificationSolution->GetLocalError(coor, time, solDOF, error);
13062  for (jVar = 0; jVar < nVar_First; jVar++) {
13063  Local_Data[jPoint][iVar] = error[jVar];
13064  iVar++;
13065  }
13066 
13067  }
13068  }
13069 
13070  /*--- New variables can be loaded to the Local_Data structure here,
13071  assuming they were registered above correctly. ---*/
13072 
13073  if ((Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) {
13074  Local_Data[jPoint][iVar] = solver[FLOW_SOL]->GetNodes()->GetVorticity(iPoint)[0]; iVar++;
13075  Local_Data[jPoint][iVar] = solver[FLOW_SOL]->GetNodes()->GetVorticity(iPoint)[1]; iVar++;
13076  if (geometry->GetnDim() == 3) {
13077  Local_Data[jPoint][iVar] = solver[FLOW_SOL]->GetNodes()->GetVorticity(iPoint)[2];
13078  iVar++;
13079  }
13080 
13081  if (nDim == 3){
13082  for (iDim = 0; iDim < nDim; iDim++) {
13083  for (unsigned short jDim = 0; jDim < nDim; jDim++) {
13084  Grad_Vel[iDim][jDim] = solver[FLOW_SOL]->GetNodes()->GetGradient_Primitive(iPoint, iDim+1, jDim);
13085  }
13086  }
13087 
13088  /*--- Q Criterion Eq 1.2 of---*/
13089  /*--- HALLER, G. (2005). An objective definition of a vortex. Journal of Fluid Mechanics, 525, 1-26. doi:10.1017/S0022112004002526 ---*/
13090 
13091  su2double s11 = Grad_Vel[0][0];
13092  su2double s12 = 0.5 * (Grad_Vel[0][1] + Grad_Vel[1][0]);
13093  su2double s13 = 0.5 * (Grad_Vel[0][2] + Grad_Vel[2][0]);
13094  su2double s22 = Grad_Vel[1][1];
13095  su2double s23 = 0.5 * (Grad_Vel[1][2] + Grad_Vel[2][1]);
13096  su2double s33 = Grad_Vel[2][2];
13097  su2double omega12 = 0.5 * (Grad_Vel[0][1] - Grad_Vel[1][0]);
13098  su2double omega13 = 0.5 * (Grad_Vel[0][2] - Grad_Vel[2][0]);
13099  su2double omega23 = 0.5 * (Grad_Vel[1][2] - Grad_Vel[2][1]);
13100 
13101  Q = 2. * pow( omega12, 2.) + 2. * pow( omega13, 2.) + 2. * pow( omega23, 2.) - \
13102  pow( s11, 2.) - pow( s22, 2.) - pow( s33, 2.0) - 2. * pow( s12, 2.) - 2. * pow( s13, 2.) - 2. * pow( s23, 2.0);
13103  Local_Data[jPoint][iVar] = Q; iVar++;
13104  }
13105  }
13106 
13107  /*--- For rotating frame problems, compute the relative velocity. ---*/
13108 
13109  if (rotating_frame) {
13110  Grid_Vel = geometry->node[iPoint]->GetGridVel();
13111  su2double *Solution = solver[FLOW_SOL]->GetNodes()->GetSolution(iPoint);
13112  Local_Data[jPoint][iVar] = Solution[1]/Solution[0] - Grid_Vel[0]; iVar++;
13113  Local_Data[jPoint][iVar] = Solution[2]/Solution[0] - Grid_Vel[1]; iVar++;
13114  if (geometry->GetnDim() == 3) {
13115  Local_Data[jPoint][iVar] = Solution[3]/Solution[0] - Grid_Vel[2];
13116  iVar++;
13117  }
13118  }
13119 
13120  /*--- Output the mesh quality metrics. ---*/
13121 
13122  if (config->GetWrt_MeshQuality()) {
13123  Local_Data[jPoint][iVar] = geometry->Orthogonality[iPoint]; iVar++;
13124  Local_Data[jPoint][iVar] = geometry->Aspect_Ratio[iPoint]; iVar++;
13125  Local_Data[jPoint][iVar] = geometry->Volume_Ratio[iPoint]; iVar++;
13126  }
13127 
13128  }
13129 
13130  /*--- Increment the point counter, as there may have been halos we
13131  skipped over during the data loading. ---*/
13132 
13133  jPoint++;
13134 
13135  }
13136 
13137 
13138  /*--- Free memory for auxiliary vectors. ---*/
13139 
13140  if ((Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) {
13141  delete [] Aux_Frict_x;
13142  delete [] Aux_Frict_y;
13143  delete [] Aux_Frict_z;
13144  delete [] Aux_Heat;
13145  delete [] Aux_yPlus;
13146  delete [] Aux_Buffet;
13147  }
13148 
13149  delete [] Local_Halo;
13150 
13151 }
13152 
13153 void COutputLegacy::LoadLocalData_IncFlow(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone) {
13154 
13155  unsigned short iDim;
13156  unsigned short Kind_Solver = config->GetKind_Solver();
13157  unsigned short nDim = geometry->GetnDim();
13158 
13159  unsigned long iVar, jVar;
13160  unsigned long iPoint, jPoint, FirstIndex = NONE, SecondIndex = NONE, iMarker, iVertex;
13161  unsigned long nVar_First = 0, nVar_Second = 0, nVar_Consv_Par = 0;
13162 
13163  su2double RefArea = config->GetRefArea();
13164  su2double RefVel2 = 0.0;
13165  su2double factor = 0.0;
13166  su2double RefDensity = 0.0, RefPressure = 0.0;
13167  su2double *Aux_Frict_x = NULL, *Aux_Frict_y = NULL, *Aux_Frict_z = NULL, *Aux_Heat = NULL, *Aux_yPlus = NULL;
13168  su2double *Grid_Vel = NULL;
13169  su2double Q, Grad_Vel[3][3] = {{0.0, 0.0, 0.0},{0.0, 0.0, 0.0},{0.0, 0.0, 0.0}};
13170 
13171  bool transition = (config->GetKind_Trans_Model() == BC);
13172  bool dynamic_grid = config->GetDynamic_Grid();
13173  bool Wrt_Halo = config->GetWrt_Halo(), isPeriodic;
13174  bool variable_density = (config->GetKind_DensityModel() == VARIABLE);
13175  bool energy = config->GetEnergy_Equation();
13176  bool weakly_coupled_heat = config->GetWeakly_Coupled_Heat();
13177  bool wrt_cp = (variable_density &&
13178  (config->GetKind_FluidModel() == INC_IDEAL_GAS_POLY));
13179  bool wrt_kt = ((config->GetKind_ConductivityModel() != CONSTANT_CONDUCTIVITY) &&
13180  (config->GetViscous()));
13181  int *Local_Halo = NULL;
13182 
13183  stringstream varname;
13184 
13185  /*--- Evaluate reference values for non-dimensionalization.
13186  For dimensional or non-dim based on initial values, use
13187  the far-field state (inf). For a custom non-dim based
13188  on user-provided reference values, use the ref values
13189  to compute the forces. ---*/
13190 
13191  if ((config->GetRef_Inc_NonDim() == DIMENSIONAL) ||
13192  (config->GetRef_Inc_NonDim() == INITIAL_VALUES)) {
13193  RefDensity = solver[FLOW_SOL]->GetDensity_Inf();
13194  RefVel2 = 0.0;
13195  for (iDim = 0; iDim < nDim; iDim++)
13196  RefVel2 += solver[FLOW_SOL]->GetVelocity_Inf(iDim)*solver[FLOW_SOL]->GetVelocity_Inf(iDim);
13197  }
13198  else if (config->GetRef_Inc_NonDim() == REFERENCE_VALUES) {
13199  RefDensity = config->GetInc_Density_Ref();
13200  RefVel2 = config->GetInc_Velocity_Ref()*config->GetInc_Velocity_Ref();
13201  }
13202 
13203  /*--- Reference pressure is always the far-field value (0.0). ---*/
13204 
13205  RefPressure = solver[FLOW_SOL]->GetPressure_Inf();
13206 
13207  /*--- Compute factor for force coefficients. ---*/
13208 
13209  factor = 1.0 / (0.5*RefDensity*RefArea*RefVel2);
13210 
13211  /*--- Use a switch statement to decide how many solver containers we have
13212  in this zone for output. ---*/
13213 
13214  switch (config->GetKind_Solver()) {
13215  case INC_EULER : case INC_NAVIER_STOKES: FirstIndex = FLOW_SOL; SecondIndex = NONE; break;
13216  case INC_RANS : FirstIndex = FLOW_SOL; SecondIndex = TURB_SOL; break;
13217  default: SecondIndex = NONE; break;
13218  }
13219 
13220  nVar_First = solver[FirstIndex]->GetnVar();
13221  if ((!energy) && (!weakly_coupled_heat)) nVar_First--;
13222  if (SecondIndex != NONE) nVar_Second = solver[SecondIndex]->GetnVar();
13223  nVar_Consv_Par = nVar_First + nVar_Second;
13224 
13225  /*--------------------------------------------------------------------------*/
13226  /*--- Step 1: Register the variables that will be output. To register a ---*/
13227  /*--- variable, two things are required. First, increment the ---*/
13228  /*--- counter for the number of variables (nVar_Par), which ---*/
13229  /*--- controls the size of the data structure allocation, i.e., ---*/
13230  /*--- the number of columns in an nPoint x nVar structure. ---*/
13231  /*--- Second, add a name for the variable to the vector that ---*/
13232  /*--- holds the string names. ---*/
13233  /*--------------------------------------------------------------------------*/
13234 
13235  /*--- All output files first need the grid coordinates. ---*/
13236 
13237  nVar_Par = 1; Variable_Names.push_back("x");
13238  nVar_Par += 1; Variable_Names.push_back("y");
13239  if (geometry->GetnDim() == 3) {
13240  nVar_Par += 1; Variable_Names.push_back("z");
13241  }
13242 
13243  /*--- At a mininum, the restarts and visualization files need the
13244  conservative variables, so these follow next. ---*/
13245 
13246  nVar_Par += nVar_Consv_Par;
13247 
13248  /*--- The incompressible solver uses primitives as the working variables. ---*/
13249 
13250  Variable_Names.push_back("Pressure");
13251  Variable_Names.push_back("Velocity_x");
13252  Variable_Names.push_back("Velocity_y");
13253  if (geometry->GetnDim() == 3) Variable_Names.push_back("Velocity_z");
13254  if (energy || weakly_coupled_heat) Variable_Names.push_back("Temperature");
13255 
13256  if (SecondIndex != NONE) {
13257  if ((config->GetKind_Turb_Model() == SST) || (config->GetKind_Turb_Model() == SST_SUST)) {
13258  Variable_Names.push_back("TKE");
13259  Variable_Names.push_back("Omega");
13260  } else {
13261  /*--- S-A variants ---*/
13262  Variable_Names.push_back("Nu_Tilde");
13263  }
13264  }
13265 
13266  /*--- If requested, register the limiter and residuals for all of the
13267  equations in the current flow problem. ---*/
13268 
13269 
13270  /*--- Add the limiters ---*/
13271 
13272  if (config->GetWrt_Limiters()) {
13273  nVar_Par += nVar_Consv_Par;
13274 
13275  Variable_Names.push_back("Limiter_Pressure");
13276  Variable_Names.push_back("Limiter_Velocity_x");
13277  Variable_Names.push_back("Limiter_Velocity_y");
13278  if (geometry->GetnDim() == 3) Variable_Names.push_back("Limiter_Velocity_z");
13279  if (energy || weakly_coupled_heat)
13280  Variable_Names.push_back("Limiter_Temperature");
13281 
13282  if (SecondIndex != NONE) {
13283  if ((config->GetKind_Turb_Model() == SST) || (config->GetKind_Turb_Model() == SST_SUST)) {
13284  Variable_Names.push_back("Limiter_TKE");
13285  Variable_Names.push_back("Limiter_Omega");
13286  } else {
13287  /*--- S-A variants ---*/
13288  Variable_Names.push_back("Limiter_Nu_Tilde");
13289  }
13290  }
13291  }
13292 
13293  /*--- Add the residuals ---*/
13294 
13295  if (config->GetWrt_Residuals()) {
13296  nVar_Par += nVar_Consv_Par;
13297 
13298  Variable_Names.push_back("Residual_Pressure");
13299  Variable_Names.push_back("Residual_Velocity_x");
13300  Variable_Names.push_back("Residual_Velocity_y");
13301  if (geometry->GetnDim() == 3) Variable_Names.push_back("Residual_Velocity_z");
13302  if (energy || weakly_coupled_heat)
13303  Variable_Names.push_back("Residual_Temperature");
13304 
13305  if (SecondIndex != NONE) {
13306  if ((config->GetKind_Turb_Model() == SST) || (config->GetKind_Turb_Model() == SST_SUST)) {
13307  Variable_Names.push_back("Residual_TKE");
13308  Variable_Names.push_back("Residual_Omega");
13309  } else {
13310  /*--- S-A variants ---*/
13311  Variable_Names.push_back("Residual_Nu_Tilde");
13312  }
13313  }
13314  }
13315 
13316  /*--- Add the grid velocity. ---*/
13317 
13318  if (dynamic_grid) {
13319  if (geometry->GetnDim() == 2) nVar_Par += 2;
13320  else if (geometry->GetnDim() == 3) nVar_Par += 3;
13321 
13322  Variable_Names.push_back("Grid_Velocity_x");
13323  Variable_Names.push_back("Grid_Velocity_y");
13324  if (geometry->GetnDim() == 3) Variable_Names.push_back("Grid_Velocity_z");
13325  }
13326 
13327  /*--- Add Cp. ---*/
13328 
13329  nVar_Par += 1;
13330  if ((config->GetTabular_FileFormat() == TAB_CSV)){
13331  Variable_Names.push_back("Pressure_Coefficient");
13332  } else {
13333  Variable_Names.push_back("C<sub>p</sub>");
13334  }
13335 
13336  /*--- Add Laminar Viscosity, Skin Friction, and Heat Flux to the restart file ---*/
13337 
13338  if ((Kind_Solver == INC_NAVIER_STOKES) || (Kind_Solver == INC_RANS)) {
13339  if ((config->GetTabular_FileFormat() == TAB_CSV)){
13340  nVar_Par += 1; Variable_Names.push_back("Laminar_Viscosity");
13341  nVar_Par += 2;
13342  Variable_Names.push_back("Skin_Friction_Coefficient_x");
13343  Variable_Names.push_back("Skin_Friction_Coefficient_y");
13344  if (geometry->GetnDim() == 3) {
13345  nVar_Par += 1; Variable_Names.push_back("Skin_Friction_Coefficient_z");
13346  }
13347  if (energy || weakly_coupled_heat) {
13348  nVar_Par += 1;
13349  Variable_Names.push_back("Heat_Flux");
13350  }
13351  } else {
13352  nVar_Par += 1; Variable_Names.push_back("<greek>m</greek>");
13353  nVar_Par += 2;
13354  Variable_Names.push_back("C<sub>f</sub>_x");
13355  Variable_Names.push_back("C<sub>f</sub>_y");
13356  if (geometry->GetnDim() == 3) {
13357  nVar_Par += 1; Variable_Names.push_back("C<sub>f</sub>_z");
13358  }
13359  if (energy || weakly_coupled_heat) {
13360  nVar_Par += 1;
13361  Variable_Names.push_back("h");
13362  }
13363  }
13364  }
13365 
13366  /*--- Add Y+ and Eddy Viscosity. ---*/
13367 
13368  if (Kind_Solver == INC_RANS) {
13369  nVar_Par += 2;
13370  if ((config->GetTabular_FileFormat() == TAB_CSV)){
13371  Variable_Names.push_back("Y_Plus");
13372  Variable_Names.push_back("Eddy_Viscosity");
13373  } else {
13374  Variable_Names.push_back("y<sup>+</sup>");
13375  Variable_Names.push_back("<greek>m</greek><sub>t</sub>");
13376  }
13377  }
13378 
13379  /*--- Add the distance to the nearest sharp edge if requested. ---*/
13380 
13381  if (config->GetWrt_SharpEdges()) {
13382  nVar_Par += 1;
13383  Variable_Names.push_back("Sharp_Edge_Dist");
13384  }
13385 
13386  /*--- Add the intermittency for the BC trans. model. ---*/
13387 
13388  if (transition) {
13389  nVar_Par += 1;
13390  if ((config->GetTabular_FileFormat() == TAB_CSV)){
13391  Variable_Names.push_back("gamma_BC");
13392  } else {
13393  Variable_Names.push_back("<greek>g</greek><sub>BC</sub>");
13394  }
13395  }
13396 
13397  if (variable_density) {
13398  nVar_Par += 1;
13399  Variable_Names.push_back("Density");
13400  }
13401 
13402  if (wrt_cp) {
13403  nVar_Par += 1;
13404  Variable_Names.push_back("Specific_Heat");
13405  }
13406 
13407  if (wrt_kt) {
13408  nVar_Par += 1;
13409  Variable_Names.push_back("Thermal_Conductivity");
13410  }
13411 
13412  if (solver[FLOW_SOL]->VerificationSolution) {
13413  if (solver[FLOW_SOL]->VerificationSolution->ExactSolutionKnown()) {
13414  nVar_Par += 2*nVar_Consv_Par;
13415  Variable_Names.push_back("Verification_Pressure");
13416  Variable_Names.push_back("Verification_Velocity_x");
13417  Variable_Names.push_back("Verification_Velocity_y");
13418  if (geometry->GetnDim() == 3) Variable_Names.push_back("Verification_Velocity_z");
13419  if (energy || weakly_coupled_heat) Variable_Names.push_back("Verification_Temperature");
13420  Variable_Names.push_back("Error_Pressure");
13421  Variable_Names.push_back("Error_Velocity_x");
13422  Variable_Names.push_back("Error_Velocity_y");
13423  if (geometry->GetnDim() == 3) Variable_Names.push_back("Error_Velocity_z");
13424  if (energy || weakly_coupled_heat) Variable_Names.push_back("Error_Temperature");
13425  }
13426  }
13427 
13428  if ((Kind_Solver == INC_NAVIER_STOKES) || (Kind_Solver == INC_RANS)) {
13429  nVar_Par += 2;
13430  Variable_Names.push_back("Vorticity_x");
13431  Variable_Names.push_back("Vorticity_y");
13432  nVar_Par += 1; Variable_Names.push_back("Vorticity_z");
13433 
13434  if (geometry->GetnDim() == 3) {
13435  nVar_Par +=1;
13436  Variable_Names.push_back("Q_Criterion");
13437  }
13438  }
13439 
13440  if (config->GetWrt_MeshQuality()) {
13441  nVar_Par +=1;
13442  Variable_Names.push_back("Orthogonality");
13443  nVar_Par +=1;
13444  Variable_Names.push_back("Aspect_Ratio");
13445  nVar_Par +=1;
13446  Variable_Names.push_back("Volume_Ratio");
13447  }
13448 
13449  /*--- New variables get registered here before the end of the loop. ---*/
13450 
13451 
13452 
13453  /*--- Auxiliary vectors for variables defined on surfaces only. ---*/
13454 
13455  if ((Kind_Solver == INC_NAVIER_STOKES) || (Kind_Solver == INC_RANS)) {
13456  Aux_Frict_x = new su2double[geometry->GetnPoint()];
13457  Aux_Frict_y = new su2double[geometry->GetnPoint()];
13458  Aux_Frict_z = new su2double[geometry->GetnPoint()];
13459  Aux_Heat = new su2double[geometry->GetnPoint()];
13460  Aux_yPlus = new su2double[geometry->GetnPoint()];
13461 
13462  /*--- First, loop through the mesh in order to find and store the
13463  value of the viscous coefficients at any surface nodes. They
13464  will be placed in an auxiliary vector and then communicated like
13465  all other volumetric variables. ---*/
13466 
13467  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
13468  Aux_Frict_x[iPoint] = 0.0;
13469  Aux_Frict_y[iPoint] = 0.0;
13470  Aux_Frict_z[iPoint] = 0.0;
13471  Aux_Heat[iPoint] = 0.0;
13472  Aux_yPlus[iPoint] = 0.0;
13473  }
13474  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
13475  if (config->GetMarker_All_Plotting(iMarker) == YES) {
13476  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
13477  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
13478  Aux_Frict_x[iPoint] = solver[FLOW_SOL]->GetCSkinFriction(iMarker, iVertex, 0);
13479  Aux_Frict_y[iPoint] = solver[FLOW_SOL]->GetCSkinFriction(iMarker, iVertex, 1);
13480  if (geometry->GetnDim() == 3) Aux_Frict_z[iPoint] = solver[FLOW_SOL]->GetCSkinFriction(iMarker, iVertex, 2);
13481  Aux_Heat[iPoint] = solver[FLOW_SOL]->GetHeatFlux(iMarker, iVertex);
13482  Aux_yPlus[iPoint] = solver[FLOW_SOL]->GetYPlus(iMarker, iVertex);
13483  }
13484  }
13485  }
13486  }
13487 
13488  /*--- Allocate the local data structure now that we know how many
13489  variables are in the output. ---*/
13490 
13491  Local_Data = new su2double*[geometry->GetnPoint()];
13492  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
13493  Local_Data[iPoint] = new su2double[nVar_Par];
13494  }
13495 
13496  Local_Halo = new int[geometry->GetnPoint()];
13497  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
13498  Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain();
13499 
13500  /*--- Search all send/recv boundaries on this partition for any periodic
13501  nodes that were part of the original domain. We want to recover these
13502  for visualization purposes. ---*/
13503 
13504  if (!Wrt_Halo) {
13505  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
13506  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
13507 
13508  /*--- Checking for less than or equal to the rank, because there may
13509  be some periodic halo nodes that send info to the same rank. ---*/
13510 
13511  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
13512  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
13513  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
13514  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1));
13515  if (isPeriodic) Local_Halo[iPoint] = false;
13516  }
13517  }
13518  }
13519  }
13520 
13521  /*--------------------------------------------------------------------------*/
13522  /*--- Step 2: Loop over all grid nodes and load up the desired data for ---*/
13523  /*--- the restart and vizualization files. Note that we need to ---*/
13524  /*--- increment the iVar variable after each variable load. ---*/
13525  /*--- The idea is that we're filling up the columns of field ---*/
13526  /*--- data for each iPoint (row) of the data structure. ---*/
13527  /*--- This data will then be sorted, communicated, and written ---*/
13528  /*--- to files automatically after this routine. Note that the ---*/
13529  /*--- ordering of the data loading MUST match the order of the ---*/
13530  /*--- variable registration above for the files to be correct. ---*/
13531  /*--------------------------------------------------------------------------*/
13532 
13533  jPoint = 0;
13534 
13535  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
13536 
13537  /*--- Check for halos & write only if requested ---*/
13538 
13539  if (!Local_Halo[iPoint] || Wrt_Halo) {
13540 
13541  /*--- Restart the column index with each new point. ---*/
13542 
13543  iVar = 0;
13544 
13545  /*--- Load the grid node coordinate values. ---*/
13546 
13547  for (iDim = 0; iDim < geometry->GetnDim(); iDim++) {
13548  Local_Data[jPoint][iVar] = geometry->node[iPoint]->GetCoord(iDim); iVar++;
13549  }
13550 
13551  /*--- Load the conservative variable states for the mean flow variables. ---*/
13552 
13553  Local_Data[jPoint][iVar] = solver[FirstIndex]->GetNodes()->GetSolution(iPoint, 0); iVar++;
13554  Local_Data[jPoint][iVar] = solver[FirstIndex]->GetNodes()->GetSolution(iPoint, 1); iVar++;
13555  Local_Data[jPoint][iVar] = solver[FirstIndex]->GetNodes()->GetSolution(iPoint, 2); iVar++;
13556  if (nDim == 3) {
13557  Local_Data[jPoint][iVar] = solver[FirstIndex]->GetNodes()->GetSolution(iPoint, 3); iVar++;
13558  }
13559  if (weakly_coupled_heat) {
13560  Local_Data[jPoint][iVar] = solver[HEAT_SOL]->GetNodes()->GetSolution(iPoint, 0);
13561  iVar++;
13562  } else if (energy) {
13563  Local_Data[jPoint][iVar] = solver[FirstIndex]->GetNodes()->GetSolution(iPoint, nDim+1);
13564  iVar++;
13565  }
13566 
13567  /*--- If this is RANS, i.e., the second solver container is not empty,
13568  then load data for the conservative turbulence variables. ---*/
13569 
13570  if (SecondIndex != NONE) {
13571  for (jVar = 0; jVar < nVar_Second; jVar++) {
13572  Local_Data[jPoint][iVar] = solver[SecondIndex]->GetNodes()->GetSolution(iPoint, jVar); iVar++;
13573  }
13574  }
13575 
13576  /*--- If limiters and/or residuals are requested. ---*/
13577 
13578  /*--- Limiters ---*/
13579  if (config->GetWrt_Limiters()) {
13580  /*--- Mean Flow Limiters ---*/
13581  for (jVar = 0; jVar < nVar_First; jVar++) {
13582  Local_Data[jPoint][iVar] = solver[FirstIndex]->GetNodes()->GetLimiter_Primitive(iPoint, jVar);
13583  iVar++;
13584  }
13585  /*--- RANS Limiters ---*/
13586  if (SecondIndex != NONE) {
13587  for (jVar = 0; jVar < nVar_Second; jVar++) {
13588  Local_Data[jPoint][iVar] = solver[SecondIndex]->GetNodes()->GetLimiter_Primitive(iPoint, jVar);
13589  iVar++;
13590  }
13591  }
13592  }
13593 
13594  /*--- Residuals ---*/
13595  if (config->GetWrt_Residuals()) {
13596  /*--- Mean Flow Residuals ---*/
13597  for (jVar = 0; jVar < nVar_First; jVar++) {
13598  Local_Data[jPoint][iVar] = solver[FirstIndex]->LinSysRes.GetBlock(iPoint, jVar);
13599  iVar++;
13600  }
13601 
13602  /*--- RANS Residuals ---*/
13603  if (SecondIndex != NONE) {
13604  for (jVar = 0; jVar < nVar_Second; jVar++) {
13605  Local_Data[jPoint][iVar] = solver[SecondIndex]->LinSysRes.GetBlock(iPoint, jVar);
13606  iVar++;
13607  }
13608  }
13609  }
13610 
13611 
13612  /*--- Load buffers with the three grid velocity components. ---*/
13613 
13614  if (dynamic_grid) {
13615  Grid_Vel = geometry->node[iPoint]->GetGridVel();
13616  Local_Data[jPoint][iVar] = Grid_Vel[0]; iVar++;
13617  Local_Data[jPoint][iVar] = Grid_Vel[1]; iVar++;
13618  if (geometry->GetnDim() == 3) {
13619  Local_Data[jPoint][iVar] = Grid_Vel[2];
13620  iVar++;
13621  }
13622  }
13623 
13624  /*--- Load data for Cp and Mach variables. ---*/
13625 
13626  Local_Data[jPoint][iVar] = (solver[FLOW_SOL]->GetNodes()->GetPressure(iPoint) - RefPressure)*factor*RefArea; iVar++;
13627 
13628  if ((Kind_Solver == INC_NAVIER_STOKES) || (Kind_Solver == INC_RANS)) {
13629 
13630  /*--- Load data for the laminar viscosity. ---*/
13631 
13632  Local_Data[jPoint][iVar] = solver[FLOW_SOL]->GetNodes()->GetLaminarViscosity(iPoint); iVar++;
13633 
13634  /*--- Load data for the skin friction, heat flux, and y-plus. ---*/
13635 
13636  Local_Data[jPoint][iVar] = Aux_Frict_x[iPoint]; iVar++;
13637  Local_Data[jPoint][iVar] = Aux_Frict_y[iPoint]; iVar++;
13638  if (geometry->GetnDim() == 3) {
13639  Local_Data[jPoint][iVar] = Aux_Frict_z[iPoint];
13640  iVar++;
13641  }
13642 
13643  if (energy || weakly_coupled_heat) {
13644  Local_Data[jPoint][iVar] = Aux_Heat[iPoint]; iVar++;
13645  }
13646 
13647  }
13648 
13649  /*--- Load data for the Eddy viscosity for RANS. ---*/
13650 
13651  if (Kind_Solver == INC_RANS) {
13652  Local_Data[jPoint][iVar] = Aux_yPlus[iPoint]; iVar++;
13653  Local_Data[jPoint][iVar] = solver[FLOW_SOL]->GetNodes()->GetEddyViscosity(iPoint); iVar++;
13654  }
13655 
13656  /*--- Load data for the distance to the nearest sharp edge. ---*/
13657 
13658  if (config->GetWrt_SharpEdges()) {
13659  Local_Data[jPoint][iVar] = geometry->node[iPoint]->GetSharpEdge_Distance(); iVar++;
13660  }
13661 
13662  /*--- Load data for the intermittency of the BC trans. model. ---*/
13663 
13664  if (transition) {
13665  Local_Data[jPoint][iVar] = solver[TURB_SOL]->GetNodes()->GetGammaBC(iPoint); iVar++;
13666  }
13667 
13668  /*--- Load density if we are solving a variable density problem. ---*/
13669 
13670  if (variable_density) {
13671  Local_Data[jPoint][iVar] = solver[FLOW_SOL]->GetNodes()->GetDensity(iPoint); iVar++;
13672  }
13673 
13674  /*--- Load Cp and conductivity if they are temperature-dependent. ---*/
13675  if (wrt_cp) {
13676  Local_Data[jPoint][iVar] = solver[FLOW_SOL]->GetNodes()->GetSpecificHeatCp(iPoint); iVar++;
13677  }
13678 
13679  if (wrt_kt) {
13680  Local_Data[jPoint][iVar] = solver[FLOW_SOL]->GetNodes()->GetThermalConductivity(iPoint); iVar++;
13681  }
13682 
13683  if (solver[FLOW_SOL]->VerificationSolution) {
13684  if (solver[FLOW_SOL]->VerificationSolution->ExactSolutionKnown()) {
13685 
13686  /*--- Get the physical time if necessary. ---*/
13687  su2double time = 0.0;
13688  if (config->GetTime_Marching()) time = config->GetPhysicalTime();
13689 
13690  /* Set the pointers to the coordinates and solution of this DOF. */
13691  const su2double *coor = geometry->node[iPoint]->GetCoord();
13692  su2double *solDOF = solver[FLOW_SOL]->GetNodes()->GetSolution(iPoint);
13693  su2double mmsSol[5] = {0.0,0.0,0.0,0.0,0.0};
13694  su2double error[5] = {0.0,0.0,0.0,0.0,0.0};
13695 
13696  /* Get the verification solution. */
13697  solver[FLOW_SOL]->VerificationSolution->GetSolution(coor, time, mmsSol);
13698  for (jVar = 0; jVar < nVar_First; jVar++) {
13699  Local_Data[jPoint][iVar] = mmsSol[jVar];
13700  iVar++;
13701  }
13702 
13703  /* Get local error from the verification solution class. */
13704  solver[FLOW_SOL]->VerificationSolution->GetLocalError(coor, time, solDOF, error);
13705  for (jVar = 0; jVar < nVar_First; jVar++) {
13706  Local_Data[jPoint][iVar] = error[jVar];
13707  iVar++;
13708  }
13709 
13710  }
13711  }
13712 
13713  if ((Kind_Solver == INC_NAVIER_STOKES) || (Kind_Solver == INC_RANS)) {
13714 
13715  Local_Data[jPoint][iVar] = solver[FLOW_SOL]->GetNodes()->GetVorticity(iPoint)[0]; iVar++;
13716  Local_Data[jPoint][iVar] = solver[FLOW_SOL]->GetNodes()->GetVorticity(iPoint)[1]; iVar++;
13717  Local_Data[jPoint][iVar] = solver[FLOW_SOL]->GetNodes()->GetVorticity(iPoint)[2]; iVar++;
13718 
13719  if (nDim == 3){
13720  for (iDim = 0; iDim < nDim; iDim++) {
13721  for (unsigned short jDim = 0; jDim < nDim; jDim++) {
13722  Grad_Vel[iDim][jDim] = solver[FLOW_SOL]->GetNodes()->GetGradient_Primitive(iPoint, iDim+1, jDim);
13723  }
13724  }
13725 
13726  /*--- Q Criterion Eq 1.2 of---*/
13727  /*--- HALLER, G. (2005). An objective definition of a vortex. Journal of Fluid Mechanics, 525, 1-26. doi:10.1017/S0022112004002526 ---*/
13728 
13729  su2double s11 = Grad_Vel[0][0];
13730  su2double s12 = 0.5 * (Grad_Vel[0][1] + Grad_Vel[1][0]);
13731  su2double s13 = 0.5 * (Grad_Vel[0][2] + Grad_Vel[2][0]);
13732  su2double s22 = Grad_Vel[1][1];
13733  su2double s23 = 0.5 * (Grad_Vel[1][2] + Grad_Vel[2][1]);
13734  su2double s33 = Grad_Vel[2][2];
13735  su2double omega12 = 0.5 * (Grad_Vel[0][1] - Grad_Vel[1][0]);
13736  su2double omega13 = 0.5 * (Grad_Vel[0][2] - Grad_Vel[2][0]);
13737  su2double omega23 = 0.5 * (Grad_Vel[1][2] - Grad_Vel[2][1]);
13738 
13739  Q = 2. * pow( omega12, 2.) + 2. * pow( omega13, 2.) + 2. * pow( omega23, 2.) - \
13740  pow( s11, 2.) - pow( s22, 2.) - pow( s33, 2.0) - 2. * pow( s12, 2.) - 2. * pow( s13, 2.) - 2. * pow( s23, 2.0);
13741 
13742  Local_Data[jPoint][iVar] = Q; iVar++;
13743  }
13744  }
13745 
13746  /*--- Output the mesh quality metrics. ---*/
13747 
13748  if (config->GetWrt_MeshQuality()) {
13749  Local_Data[jPoint][iVar] = geometry->Orthogonality[iPoint]; iVar++;
13750  Local_Data[jPoint][iVar] = geometry->Aspect_Ratio[iPoint]; iVar++;
13751  Local_Data[jPoint][iVar] = geometry->Volume_Ratio[iPoint]; iVar++;
13752  }
13753 
13754  /*--- New variables can be loaded to the Local_Data structure here,
13755  assuming they were registered above correctly. ---*/
13756 
13757  }
13758 
13759  /*--- Increment the point counter, as there may have been halos we
13760  skipped over during the data loading. ---*/
13761 
13762  jPoint++;
13763 
13764  }
13765 
13766 
13767  /*--- Free memory for auxiliary vectors. ---*/
13768 
13769  if ((Kind_Solver == INC_NAVIER_STOKES) || (Kind_Solver == INC_RANS)) {
13770  delete [] Aux_Frict_x;
13771  delete [] Aux_Frict_y;
13772  delete [] Aux_Frict_z;
13773  delete [] Aux_Heat;
13774  delete [] Aux_yPlus;
13775  }
13776 
13777  delete [] Local_Halo;
13778 
13779 }
13780 
13781 void COutputLegacy::LoadLocalData_AdjFlow(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone) {
13782 
13783  unsigned short iDim;
13784  unsigned short Kind_Solver = config->GetKind_Solver();
13785  unsigned short nDim = geometry->GetnDim();
13786 
13787  unsigned long iVar, jVar;
13788  unsigned long iPoint, jPoint, FirstIndex = NONE, SecondIndex = NONE, iMarker, iVertex;
13789  unsigned long nVar_First = 0, nVar_Second = 0, nVar_Consv_Par = 0;
13790 
13791  su2double *Aux_Sens = NULL;
13792  su2double *Grid_Vel = NULL;
13793  su2double *Normal, Area;
13794 
13795  bool incompressible = (config->GetKind_Regime() == INCOMPRESSIBLE);
13796  bool dynamic_grid = config->GetDynamic_Grid();
13797 
13798  bool Wrt_Halo = config->GetWrt_Halo(), isPeriodic;
13799 
13800  int *Local_Halo;
13801 
13802  stringstream varname;
13803 
13804  /*--- Use a switch statement to decide how many solver containers we have
13805  in this zone for output. ---*/
13806 
13807  switch (config->GetKind_Solver()) {
13808  case ADJ_EULER : case ADJ_NAVIER_STOKES : FirstIndex = ADJFLOW_SOL; SecondIndex = NONE; break;
13809  case ADJ_RANS : FirstIndex = ADJFLOW_SOL; if (config->GetFrozen_Visc_Cont()) SecondIndex = NONE; else SecondIndex = ADJTURB_SOL; break;
13812  FirstIndex = ADJFLOW_SOL; SecondIndex = NONE; break;
13813  case DISC_ADJ_RANS: case DISC_ADJ_INC_RANS: FirstIndex = ADJFLOW_SOL; if (config->GetFrozen_Visc_Disc()) SecondIndex = NONE; else SecondIndex = ADJTURB_SOL; break;
13814  }
13815 
13816  nVar_First = solver[FirstIndex]->GetnVar();
13817  if (SecondIndex != NONE) nVar_Second = solver[SecondIndex]->GetnVar();
13818  nVar_Consv_Par = nVar_First + nVar_Second;
13819 
13820  /*--------------------------------------------------------------------------*/
13821  /*--- Step 1: Register the variables that will be output. To register a ---*/
13822  /*--- variable, two things are required. First, increment the ---*/
13823  /*--- counter for the number of variables (nVar_Par), which ---*/
13824  /*--- controls the size of the data structure allocation, i.e., ---*/
13825  /*--- the number of columns in an nPoint x nVar structure. ---*/
13826  /*--- Second, add a name for the variable to the vector that ---*/
13827  /*--- holds the string names. ---*/
13828  /*--------------------------------------------------------------------------*/
13829 
13830  /*--- All output files first need the grid coordinates. ---*/
13831 
13832  nVar_Par = 1; Variable_Names.push_back("x");
13833  nVar_Par += 1; Variable_Names.push_back("y");
13834  if (geometry->GetnDim() == 3) {
13835  nVar_Par += 1; Variable_Names.push_back("z");
13836  }
13837 
13838  /*--- At a mininum, the restarts and visualization files need the
13839  conservative variables, so these follow next. ---*/
13840 
13841  nVar_Par += nVar_Consv_Par;
13842 
13843  /*--- For now, leave the names as "Conservative_", etc., in order
13844  to avoid confusion with the serial version, which still prints these
13845  names. Names can be set alternatively by using the commented code
13846  below. ---*/
13847 
13848  if (incompressible) {
13849  Variable_Names.push_back("Adjoint_Pressure");
13850  Variable_Names.push_back("Adjoint_Velocity_x");
13851  Variable_Names.push_back("Adjoint_Velocity_y");
13852  if (geometry->GetnDim() == 3) Variable_Names.push_back("Adjoint_Velocity_z");
13853  Variable_Names.push_back("Adjoint_Temperature");
13854  } else {
13855  Variable_Names.push_back("Adjoint_Density");
13856  Variable_Names.push_back("Adjoint_Momentum_x");
13857  Variable_Names.push_back("Adjoint_Momentum_y");
13858  if (geometry->GetnDim() == 3)
13859  Variable_Names.push_back("Adjoint_Momentum_z");
13860  Variable_Names.push_back("Adjoint_Energy");
13861  }
13862  if (SecondIndex != NONE) {
13863  if ((config->GetKind_Turb_Model() == SST) || (config->GetKind_Turb_Model() == SST_SUST)) {
13864  Variable_Names.push_back("Adjoint_TKE");
13865  Variable_Names.push_back("Adjoint_Omega");
13866  } else {
13867  /*--- S-A variants ---*/
13868  Variable_Names.push_back("Adjoint_Nu_Tilde");
13869  }
13870  }
13871 
13872  /*--- For the discrete adjoint, we have the full field of sensitivity
13873  in each coordinate direction. ---*/
13874 
13875  if ((Kind_Solver == DISC_ADJ_EULER) ||
13876  (Kind_Solver == DISC_ADJ_NAVIER_STOKES) ||
13877  (Kind_Solver == DISC_ADJ_RANS) ||
13878  (Kind_Solver == DISC_ADJ_INC_EULER) ||
13879  (Kind_Solver == DISC_ADJ_INC_NAVIER_STOKES) ||
13880  (Kind_Solver == DISC_ADJ_INC_RANS)) {
13881  nVar_Par += nDim;
13882  Variable_Names.push_back("Sensitivity_x");
13883  Variable_Names.push_back("Sensitivity_y");
13884  if (geometry->GetnDim()== 3)
13885  Variable_Names.push_back("Sensitivity_z");
13886  }
13887 
13888  /*--- If requested, register the limiter and residuals for all of the
13889  equations in the current flow problem. ---*/
13890 
13891  /*--- Add the limiters ---*/
13892 
13893  if (config->GetWrt_Limiters()) {
13894  nVar_Par += nVar_Consv_Par;
13895  if (incompressible) {
13896  Variable_Names.push_back("Limiter_Adjoint_Pressure");
13897  Variable_Names.push_back("Limiter_Adjoint_Velocity_x");
13898  Variable_Names.push_back("Limiter_Adjoint_Velocity_y");
13899  if (geometry->GetnDim() == 3) Variable_Names.push_back("Limiter_Adjoint_Velocity_z");
13900  Variable_Names.push_back("Limiter_Adjoint_Temperature");
13901  } else {
13902  Variable_Names.push_back("Limiter_Adjoint_Density");
13903  Variable_Names.push_back("Limiter_Adjoint_Momentum_x");
13904  Variable_Names.push_back("Limiter_Adjoint_Momentum_y");
13905  if (geometry->GetnDim() == 3)
13906  Variable_Names.push_back("Limiter_Adjoint_Momentum_z");
13907  Variable_Names.push_back("Limiter_Adjoint_Energy");
13908  }
13909  if (SecondIndex != NONE) {
13910  if ((config->GetKind_Turb_Model() == SST) || (config->GetKind_Turb_Model() == SST_SUST)) {
13911  Variable_Names.push_back("Limiter_Adjoint_TKE");
13912  Variable_Names.push_back("Limiter_Adjoint_Omega");
13913  } else {
13914  /*--- S-A variants ---*/
13915  Variable_Names.push_back("Limiter_Adjoint_Nu_Tilde");
13916  }
13917  }
13918  }
13919 
13920  /*--- Add the residuals ---*/
13921 
13922  if (config->GetWrt_Residuals()) {
13923  nVar_Par += nVar_Consv_Par;
13924  if (incompressible) {
13925  Variable_Names.push_back("Residual_Adjoint_Pressure");
13926  Variable_Names.push_back("Residual_Adjoint_Velocity_x");
13927  Variable_Names.push_back("Residual_Adjoint_Velocity_y");
13928  if (geometry->GetnDim() == 3) Variable_Names.push_back("Residual_Adjoint_Velocity_z");
13929  Variable_Names.push_back("Residual_Adjoint_Temperature");
13930  } else {
13931  Variable_Names.push_back("Residual_Adjoint_Density");
13932  Variable_Names.push_back("Residual_Adjoint_Momentum_x");
13933  Variable_Names.push_back("Residual_Adjoint_Momentum_y");
13934  if (geometry->GetnDim() == 3)
13935  Variable_Names.push_back("Residual_Adjoint_Momentum_z");
13936  Variable_Names.push_back("Residual_Adjoint_Energy");
13937  }
13938  if (SecondIndex != NONE) {
13939  if ((config->GetKind_Turb_Model() == SST) || (config->GetKind_Turb_Model() == SST_SUST)) {
13940  Variable_Names.push_back("Residual_Adjoint_TKE");
13941  Variable_Names.push_back("Residual_Adjoint_Omega");
13942  } else {
13943  /*--- S-A variants ---*/
13944  Variable_Names.push_back("Residual_Adjoint_Nu_Tilde");
13945  }
13946  }
13947  }
13948 
13949  /*--- Add the grid velocity. ---*/
13950 
13951  if (dynamic_grid) {
13952  if (geometry->GetnDim() == 2) nVar_Par += 2;
13953  else if (geometry->GetnDim() == 3) nVar_Par += 3;
13954  Variable_Names.push_back("Grid_Velocity_x");
13955  Variable_Names.push_back("Grid_Velocity_y");
13956  if (geometry->GetnDim() == 3) Variable_Names.push_back("Grid_Velocity_z");
13957  }
13958 
13959  /*--- All adjoint solvers write the surface sensitivity. ---*/
13960 
13961  nVar_Par += 1; Variable_Names.push_back("Surface_Sensitivity");
13962 
13963  /*--- For the continouus adjoint, we write either convective scheme's
13964  dissipation sensor (centered) or limiter (uwpind) for adj. density. ---*/
13965 
13966  if (( Kind_Solver == ADJ_EULER ) ||
13967  ( Kind_Solver == ADJ_NAVIER_STOKES ) ||
13968  ( Kind_Solver == ADJ_RANS )) {
13969  nVar_Par += 1;
13970  if (config->GetKind_ConvNumScheme() == SPACE_CENTERED) {
13971  Variable_Names.push_back("Dissipation_Sensor");
13972  } else {
13973  Variable_Names.push_back("Limiter_Adjoint_Density");
13974  }
13975  }
13976 
13977  /*--- New variables get registered here before the end of the loop. ---*/
13978 
13979 
13980 
13981  /*--- Auxiliary vectors for variables defined on surfaces only. ---*/
13982 
13983  Aux_Sens = new su2double[geometry->GetnPoint()];
13984 
13985  /*--- First, loop through the mesh in order to find and store the
13986  value of the viscous coefficients at any surface nodes. They
13987  will be placed in an auxiliary vector and then communicated like
13988  all other volumetric variables. ---*/
13989 
13990  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
13991  Aux_Sens[iPoint] = 0.0;
13992  }
13993  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++)
13994  if (config->GetMarker_All_Plotting(iMarker) == YES) {
13995  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
13996  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
13997  Normal = geometry->vertex[iMarker][iVertex]->GetNormal();
13998  Area = 0.0;
13999  for (iDim = 0; iDim < nDim; iDim++) Area += Normal[iDim]*Normal[iDim];
14000  Area = sqrt (Area);
14001  Aux_Sens[iPoint] = solver[ADJFLOW_SOL]->GetCSensitivity(iMarker, iVertex)/Area;
14002  }
14003  }
14004 
14005  /*--- Allocate the local data structure now that we know how many
14006  variables are in the output. ---*/
14007 
14008  Local_Data = new su2double*[geometry->GetnPoint()];
14009  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
14010  Local_Data[iPoint] = new su2double[nVar_Par];
14011  }
14012 
14013  Local_Halo = new int[geometry->GetnPoint()];
14014  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
14015  Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain();
14016 
14017  /*--- Search all send/recv boundaries on this partition for any periodic
14018  nodes that were part of the original domain. We want to recover these
14019  for visualization purposes. ---*/
14020 
14021  if (!Wrt_Halo) {
14022  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
14023  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
14024 
14025  /*--- Checking for less than or equal to the rank, because there may
14026  be some periodic halo nodes that send info to the same rank. ---*/
14027 
14028  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
14029  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
14030  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
14031  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1));
14032  if (isPeriodic) Local_Halo[iPoint] = false;
14033  }
14034  }
14035  }
14036  }
14037 
14038  /*--------------------------------------------------------------------------*/
14039  /*--- Step 2: Loop over all grid nodes and load up the desired data for ---*/
14040  /*--- the restart and vizualization files. Note that we need to ---*/
14041  /*--- increment the iVar variable after each variable load. ---*/
14042  /*--- The idea is that we're filling up the columns of field ---*/
14043  /*--- data for each iPoint (row) of the data structure. This ---*/
14044  /*--- This data will then be sorted, communicated, and written ---*/
14045  /*--- to files automatically after this routine. Note that the ---*/
14046  /*--- ordering of the data loading MUST match the order of the ---*/
14047  /*--- variable registration above for the files to be correct. ---*/
14048  /*--------------------------------------------------------------------------*/
14049 
14050  jPoint = 0;
14051 
14052  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
14053 
14054  /*--- Check for halos & write only if requested ---*/
14055 
14056  if (!Local_Halo[iPoint] || Wrt_Halo) {
14057 
14058  /*--- Restart the column index with each new point. ---*/
14059 
14060  iVar = 0;
14061 
14062  /*--- Load the grid node coordinate values. ---*/
14063 
14064  for (iDim = 0; iDim < geometry->GetnDim(); iDim++) {
14065  Local_Data[jPoint][iVar] = geometry->node[iPoint]->GetCoord(iDim);
14066  if (config->GetSystemMeasurements() == US)
14067  Local_Data[jPoint][iVar] *= 12.0;
14068  iVar++;
14069  }
14070 
14071  /*--- Load the conservative variable states for the mean flow variables.
14072  If requested, load the limiters and residuals as well. ---*/
14073 
14074  for (jVar = 0; jVar < nVar_First; jVar++) {
14075  Local_Data[jPoint][iVar] = solver[FirstIndex]->GetNodes()->GetSolution(iPoint, jVar);
14076  iVar++;
14077  }
14078 
14079 
14080  /*--- If this is Adj. RANS, i.e., the second solver container is not empty,
14081  then load data for the conservative turbulence variables and the
14082  limiters / residuals (if requested). ----*/
14083 
14084  if (SecondIndex != NONE) {
14085  for (jVar = 0; jVar < nVar_Second; jVar++) {
14086  Local_Data[jPoint][iVar] = solver[SecondIndex]->GetNodes()->GetSolution(iPoint, jVar);
14087  iVar++;
14088  }
14089  }
14090 
14091  /*--- Load data for the discrete sensitivities. ---*/
14092 
14093  if ((Kind_Solver == DISC_ADJ_EULER) ||
14094  (Kind_Solver == DISC_ADJ_NAVIER_STOKES) ||
14095  (Kind_Solver == DISC_ADJ_RANS) ||
14096  (Kind_Solver == DISC_ADJ_INC_EULER) ||
14097  (Kind_Solver == DISC_ADJ_INC_NAVIER_STOKES) ||
14098  (Kind_Solver == DISC_ADJ_INC_RANS)) {
14099  Local_Data[jPoint][iVar] = solver[ADJFLOW_SOL]->GetNodes()->GetSensitivity(iPoint, 0); iVar++;
14100  Local_Data[jPoint][iVar] = solver[ADJFLOW_SOL]->GetNodes()->GetSensitivity(iPoint, 1); iVar++;
14101  if (geometry->GetnDim()== 3) {
14102  Local_Data[jPoint][iVar] = solver[ADJFLOW_SOL]->GetNodes()->GetSensitivity(iPoint, 2);
14103  iVar++;
14104  }
14105  }
14106 
14107  if (config->GetWrt_Limiters()) {
14108  for (jVar = 0; jVar < nVar_First; jVar++) {
14109  Local_Data[jPoint][iVar] = solver[FirstIndex]->GetNodes()->GetLimiter(iPoint, jVar);
14110  iVar++;
14111  }
14112  if (SecondIndex != NONE) {
14113  for (jVar = 0; jVar < nVar_Second; jVar++) {
14114  Local_Data[jPoint][iVar] = solver[SecondIndex]->GetNodes()->GetLimiter(iPoint, jVar);
14115  iVar++;
14116  }
14117  }
14118  }
14119 
14120  if (config->GetWrt_Residuals()) {
14121  for (jVar = 0; jVar < nVar_First; jVar++) {
14122  if (!config->GetDiscrete_Adjoint()) {
14123  Local_Data[jPoint][iVar] = solver[FirstIndex]->LinSysRes.GetBlock(iPoint, jVar);
14124  } else {
14125  Local_Data[jPoint][iVar] = solver[FirstIndex]->GetNodes()->GetSolution(iPoint, jVar) -
14126  solver[FirstIndex]->GetNodes()->GetSolution_Old(iPoint, jVar);
14127  }
14128  iVar++;
14129  }
14130  if (SecondIndex != NONE) {
14131  for (jVar = 0; jVar < nVar_Second; jVar++) {
14132  if (!config->GetDiscrete_Adjoint()) {
14133  Local_Data[jPoint][iVar] = solver[SecondIndex]->LinSysRes.GetBlock(iPoint, jVar);
14134  } else {
14135  Local_Data[jPoint][iVar] = solver[SecondIndex]->GetNodes()->GetSolution(iPoint, jVar) -
14136  solver[SecondIndex]->GetNodes()->GetSolution_Old(iPoint, jVar);
14137  }
14138  iVar++;
14139  }
14140  }
14141  }
14142 
14143  /*--- Load buffers with the three grid velocity components. ---*/
14144 
14145  if (dynamic_grid) {
14146  Grid_Vel = geometry->node[iPoint]->GetGridVel();
14147  Local_Data[jPoint][iVar] = Grid_Vel[0]; iVar++;
14148  Local_Data[jPoint][iVar] = Grid_Vel[1]; iVar++;
14149  if (geometry->GetnDim() == 3) {
14150  Local_Data[jPoint][iVar] = Grid_Vel[2];
14151  iVar++;
14152  }
14153  }
14154 
14155  /*--- Load data for the surface sensitivity. ---*/
14156 
14157  Local_Data[iPoint][iVar] = Aux_Sens[iPoint]; iVar++;
14158 
14159  /*--- Load data for the convective scheme sensor. ---*/
14160 
14161  if (( Kind_Solver == ADJ_EULER ) ||
14162  ( Kind_Solver == ADJ_NAVIER_STOKES ) ||
14163  ( Kind_Solver == ADJ_RANS )) {
14164  if (config->GetKind_ConvNumScheme() == SPACE_CENTERED) {
14165  Local_Data[jPoint][iVar] = solver[ADJFLOW_SOL]->GetNodes()->GetSensor(iPoint); iVar++;
14166  } else {
14167  Local_Data[jPoint][iVar] = solver[ADJFLOW_SOL]->GetNodes()->GetLimiter(iPoint, 0); iVar++;
14168  }
14169  }
14170 
14171  /*--- New variables can be loaded to the Local_Data structure here,
14172  assuming they were registered above correctly. ---*/
14173 
14174  }
14175 
14176  /*--- Increment the point counter, as there may have been halos we
14177  skipped over during the data loading. ---*/
14178 
14179  jPoint++;
14180  }
14181 
14182 
14183  /*--- Free memory for auxiliary vectors. ---*/
14184 
14185  delete [] Aux_Sens;
14186  delete [] Local_Halo;
14187 
14188 }
14189 
14190 void COutputLegacy::LoadLocalData_Elasticity(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone) {
14191 
14192  unsigned short iDim;
14193 
14194  unsigned long iVar, jVar;
14195  unsigned long iPoint, jPoint, FirstIndex = NONE, iMarker, iVertex;
14196  unsigned long nVar_First = 0, nVar_Consv_Par = 0;
14197 
14198  su2double *Node_Vel = NULL, *Node_Accel = NULL, *Stress = NULL;
14199 
14200  bool Wrt_Halo = config->GetWrt_Halo(), isPeriodic;
14201  int *Local_Halo = NULL;
14202 
14203  stringstream varname;
14204 
14205  /*--- Use a switch statement to decide how many solver containers we have
14206  in this zone for output. ---*/
14207 
14208  switch (config->GetKind_Solver()) {
14209  case FEM_ELASTICITY: FirstIndex = FEA_SOL; break;
14210  case DISC_ADJ_FEM: FirstIndex = ADJFEA_SOL; break;
14211  }
14212 
14213  nVar_First = solver[FirstIndex]->GetnVar();
14214  nVar_Consv_Par = nVar_First;
14215 
14216  /*--------------------------------------------------------------------------*/
14217  /*--- Step 1: Register the variables that will be output. To register a ---*/
14218  /*--- variable, two things are required. First, increment the ---*/
14219  /*--- counter for the number of variables (nVar_Par), which ---*/
14220  /*--- controls the size of the data structure allocation, i.e., ---*/
14221  /*--- the number of columns in an nPoint x nVar structure. ---*/
14222  /*--- Second, add a name for the variable to the vector that ---*/
14223  /*--- holds the string names. ---*/
14224  /*--------------------------------------------------------------------------*/
14225 
14226  /*--- All output files first need the grid coordinates. ---*/
14227 
14228  nVar_Par = 1; Variable_Names.push_back("x");
14229  nVar_Par += 1; Variable_Names.push_back("y");
14230  if (geometry->GetnDim() == 3) {
14231  nVar_Par += 1; Variable_Names.push_back("z");
14232  }
14233 
14234  /*--- At a mininum, the restarts and visualization files need the
14235  conservative variables, so these follow next. ---*/
14236 
14237  nVar_Par += nVar_Consv_Par;
14238 
14239  /*--- For now, leave the names as "Conservative_", etc., in order
14240  to avoid confusion with the serial version, which still prints these
14241  names. Names can be set alternatively by using the commented code
14242  below. ---*/
14243 
14244  Variable_Names.push_back("Displacement_x");
14245  Variable_Names.push_back("Displacement_y");
14246  if (geometry->GetnDim() == 3)
14247  Variable_Names.push_back("Displacement_z");
14248 
14249  /*--- If requested, register the limiter and residuals for all of the
14250  equations in the current flow problem. ---*/
14251 
14252 
14253  /*--- Add the residuals ---*/
14254 
14255  if (config->GetWrt_Residuals()) {
14256  nVar_Par += nVar_Consv_Par;
14257  Variable_Names.push_back("Residual_Displacement_x");
14258  Variable_Names.push_back("Residual_Displacement_y");
14259  if (geometry->GetnDim() == 3)
14260  Variable_Names.push_back("Residual_Displacement_z");
14261  }
14262 
14263  /*--- If the analysis is dynamic... ---*/
14264  if (config->GetTime_Domain()) {
14265 
14266  /*--- Velocities ---*/
14267  nVar_Par += 2;
14268  Variable_Names.push_back("Velocity_x");
14269  Variable_Names.push_back("Velocity_y");
14270  if (geometry->GetnDim() == 3) {
14271  nVar_Par += 1;
14272  Variable_Names.push_back("Velocity_z");
14273  }
14274 
14275  /*--- Accelerations ---*/
14276  nVar_Par += 2;
14277  Variable_Names.push_back("Acceleration_x");
14278  Variable_Names.push_back("Acceleration_y");
14279  if (geometry->GetnDim() == 3) {
14280  nVar_Par += 1;
14281  Variable_Names.push_back("Acceleration_z");
14282  }
14283  }
14284 
14285  if (!(config->GetDiscrete_Adjoint())) {
14286 
14287  /*--- Add the stresses. ---*/
14288 
14289  nVar_Par += 3;
14290  Variable_Names.push_back("Sxx");
14291  Variable_Names.push_back("Syy");
14292  Variable_Names.push_back("Sxy");
14293  if (geometry->GetnDim() == 3) {
14294  nVar_Par += 3;
14295  Variable_Names.push_back("Szz");
14296  Variable_Names.push_back("Sxz");
14297  Variable_Names.push_back("Syz");
14298  }
14299 
14300  /*--- Add the Von Mises Stress. ---*/
14301 
14302  nVar_Par += 1;
14303  Variable_Names.push_back("Von_Mises_Stress");
14304 
14305  }
14306 
14307  /*--- New variables get registered here before the end of the loop. ---*/
14308 
14309 
14310 
14311  /*--- Allocate the local data structure now that we know how many
14312  variables are in the output. ---*/
14313 
14314  Local_Data = new su2double*[geometry->GetnPoint()];
14315  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
14316  Local_Data[iPoint] = new su2double[nVar_Par];
14317  }
14318 
14319  Local_Halo = new int[geometry->GetnPoint()];
14320  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
14321  Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain();
14322 
14323  /*--- Search all send/recv boundaries on this partition for any periodic
14324  nodes that were part of the original domain. We want to recover these
14325  for visualization purposes. ---*/
14326 
14327  if (!Wrt_Halo) {
14328  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
14329  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
14330 
14331  /*--- Checking for less than or equal to the rank, because there may
14332  be some periodic halo nodes that send info to the same rank. ---*/
14333 
14334  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
14335  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
14336  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
14337  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1));
14338  if (isPeriodic) Local_Halo[iPoint] = false;
14339  }
14340  }
14341  }
14342  }
14343 
14344  /*--------------------------------------------------------------------------*/
14345  /*--- Step 2: Loop over all grid nodes and load up the desired data for ---*/
14346  /*--- the restart and vizualization files. Note that we need to ---*/
14347  /*--- increment the iVar variable after each variable load. ---*/
14348  /*--- The idea is that we're filling up the columns of field ---*/
14349  /*--- data for each iPoint (row) of the data structure. This ---*/
14350  /*--- This data will then be sorted, communicated, and written ---*/
14351  /*--- to files automatically after this routine. Note that the ---*/
14352  /*--- ordering of the data loading MUST match the order of the ---*/
14353  /*--- variable registration above for the files to be correct. ---*/
14354  /*--------------------------------------------------------------------------*/
14355 
14356  jPoint = 0;
14357 
14358  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
14359 
14360  /*--- Check for halos & write only if requested ---*/
14361 
14362  if (!Local_Halo[iPoint] || Wrt_Halo) {
14363 
14364  /*--- Restart the column index with each new point. ---*/
14365 
14366  iVar = 0;
14367 
14368  /*--- Load the grid node coordinate values. ---*/
14369 
14370  for (iDim = 0; iDim < geometry->GetnDim(); iDim++) {
14371  Local_Data[jPoint][iVar] = geometry->node[iPoint]->GetCoord(iDim);
14372  if (config->GetSystemMeasurements() == US)
14373  Local_Data[jPoint][iVar] *= 12.0;
14374  iVar++;
14375  }
14376 
14377  /*--- Load the conservative variable states for the mean flow variables.
14378  If requested, load the limiters and residuals as well. ---*/
14379 
14380  for (jVar = 0; jVar < nVar_First; jVar++) {
14381  Local_Data[jPoint][iVar] = solver[FirstIndex]->GetNodes()->GetSolution(iPoint, jVar);
14382  iVar++;
14383  }
14384 
14385  if (config->GetWrt_Residuals()) {
14386  for (jVar = 0; jVar < nVar_First; jVar++) {
14387  Local_Data[jPoint][iVar] = solver[FirstIndex]->LinSysRes.GetBlock(iPoint, jVar);
14388  iVar++;
14389  }
14390  }
14391 
14392 
14393 
14394  /*--- Load the velocities and accelerations (dynamic calculations). ---*/
14395 
14396  if (config->GetTime_Domain()) {
14397 
14398  /*--- Velocities ---*/
14399 
14400  Node_Vel = solver[FEA_SOL]->GetNodes()->GetSolution_Vel(iPoint);
14401  Local_Data[jPoint][iVar] = Node_Vel[0]; iVar++;
14402  Local_Data[jPoint][iVar] = Node_Vel[1]; iVar++;
14403  if (geometry->GetnDim() == 3) {
14404  Local_Data[jPoint][iVar] = Node_Vel[2];
14405  iVar++;
14406  }
14407 
14408  /*--- Accelerations ---*/
14409 
14410  Node_Accel = solver[FEA_SOL]->GetNodes()->GetSolution_Accel(iPoint);
14411  Local_Data[jPoint][iVar] = Node_Accel[0]; iVar++;
14412  Local_Data[jPoint][iVar] = Node_Accel[1]; iVar++;
14413  if (geometry->GetnDim() == 3) {
14414  Local_Data[jPoint][iVar] = Node_Accel[2];
14415  iVar++;
14416  }
14417  }
14418 
14419  if (!(config->GetDiscrete_Adjoint())) {
14420 
14421  /*--- Add the stresses. ---*/
14422 
14423  Stress = solver[FEA_SOL]->GetNodes()->GetStress_FEM(iPoint);
14424 
14425  /*--- Sigma xx ---*/
14426  Local_Data[jPoint][iVar] = Stress[0]; iVar++;
14427  /*--- Sigma yy ---*/
14428  Local_Data[jPoint][iVar] = Stress[1]; iVar++;
14429  /*--- Sigma xy ---*/
14430  Local_Data[jPoint][iVar] = Stress[2]; iVar++;
14431 
14432  if (geometry->GetnDim() == 3) {
14433  /*--- Sigma zz ---*/
14434  Local_Data[jPoint][iVar] = Stress[3]; iVar++;
14435  /*--- Sigma xz ---*/
14436  Local_Data[jPoint][iVar] = Stress[4]; iVar++;
14437  /*--- Sigma yz ---*/
14438  Local_Data[jPoint][iVar] = Stress[5]; iVar++;
14439  }
14440 
14441  /*--- Add the Von Mises Stress. ---*/
14442 
14443  Local_Data[iPoint][iVar] = solver[FEA_SOL]->GetNodes()->GetVonMises_Stress(iPoint); iVar++;
14444 
14445 
14446  /*--- New variables can be loaded to the Local_Data structure here,
14447  assuming they were registered above correctly. ---*/
14448 
14449  }
14450 
14451 
14452 
14453  /*--- Increment the point counter, as there may have been halos we
14454  skipped over during the data loading. ---*/
14455 
14456  jPoint++;
14457  }
14458  }
14459 
14460  /*--- Free memory for auxiliary vectors. ---*/
14461 
14462  delete [] Local_Halo;
14463 
14464 }
14465 
14466 void COutputLegacy::LoadLocalData_Base(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone) {
14467 
14468  unsigned short iDim;
14469 
14470  unsigned long iVar, jVar;
14471  unsigned long iPoint, jPoint, FirstIndex = NONE, iMarker, iVertex;
14472  unsigned long nVar_First = 0, nVar_Consv_Par = 0;
14473 
14474  bool Wrt_Halo = config->GetWrt_Halo(), isPeriodic;
14475 
14476  int *Local_Halo;
14477 
14478  stringstream varname;
14479 
14480  /*--- Use a switch statement to decide how many solver containers we have
14481  in this zone for output. ---*/
14482 
14483  switch (config->GetKind_Solver()) {
14484  case HEAT_EQUATION_FVM: FirstIndex = HEAT_SOL; break;
14485  }
14486 
14487  nVar_First = solver[FirstIndex]->GetnVar();
14488  nVar_Consv_Par = nVar_First;
14489 
14490  /*--------------------------------------------------------------------------*/
14491  /*--- Step 1: Register the variables that will be output. To register a ---*/
14492  /*--- variable, two things are required. First, increment the ---*/
14493  /*--- counter for the number of variables (nVar_Par), which ---*/
14494  /*--- controls the size of the data structure allocation, i.e., ---*/
14495  /*--- the number of columns in an nPoint x nVar structure. ---*/
14496  /*--- Second, add a name for the variable to the vector that ---*/
14497  /*--- holds the string names. ---*/
14498  /*--------------------------------------------------------------------------*/
14499 
14500  /*--- All output files first need the grid coordinates. ---*/
14501 
14502  nVar_Par = 1; Variable_Names.push_back("x");
14503  nVar_Par += 1; Variable_Names.push_back("y");
14504  if (geometry->GetnDim() == 3) {
14505  nVar_Par += 1; Variable_Names.push_back("z");
14506  }
14507 
14508  /*--- At a mininum, the restarts and visualization files need the
14509  conservative variables, so these follow next. ---*/
14510 
14511  nVar_Par += nVar_Consv_Par;
14512  for (iVar = 0; iVar < nVar_Consv_Par; iVar++) {
14513  varname << "Conservative_" << iVar+1;
14514  Variable_Names.push_back(varname.str());
14515  varname.str("");
14516  }
14517 
14518  /*--- If requested, register the residuals for all of the
14519  equations in the current problem. ---*/
14520 
14521 
14522  /*--- Add the residuals ---*/
14523 
14524  if (config->GetWrt_Residuals()) {
14525  nVar_Par += nVar_Consv_Par;
14526  for (iVar = 0; iVar < nVar_Consv_Par; iVar++) {
14527  varname << "Residual_" << iVar+1;
14528  Variable_Names.push_back(varname.str());
14529  varname.str("");
14530  }
14531  }
14532 
14533  /*--- New variables get registered here before the end of the loop. ---*/
14534 
14535 
14536 
14537  /*--- Allocate the local data structure now that we know how many
14538  variables are in the output. ---*/
14539 
14540  Local_Data = new su2double*[geometry->GetnPoint()];
14541  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
14542  Local_Data[iPoint] = new su2double[nVar_Par];
14543  }
14544 
14545  Local_Halo = new int[geometry->GetnPoint()];
14546  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
14547  Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain();
14548 
14549  /*--- Search all send/recv boundaries on this partition for any periodic
14550  nodes that were part of the original domain. We want to recover these
14551  for visualization purposes. ---*/
14552 
14553  if (!Wrt_Halo) {
14554  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
14555  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
14556 
14557  /*--- Checking for less than or equal to the rank, because there may
14558  be some periodic halo nodes that send info to the same rank. ---*/
14559 
14560  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
14561  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
14562  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
14563  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1));
14564  if (isPeriodic) Local_Halo[iPoint] = false;
14565  }
14566  }
14567  }
14568  }
14569 
14570  /*--------------------------------------------------------------------------*/
14571  /*--- Step 2: Loop over all grid nodes and load up the desired data for ---*/
14572  /*--- the restart and vizualization files. Note that we need to ---*/
14573  /*--- increment the iVar variable after each variable load. ---*/
14574  /*--- The idea is that we're filling up the columns of field ---*/
14575  /*--- data for each iPoint (row) of the data structure. This ---*/
14576  /*--- This data will then be sorted, communicated, and written ---*/
14577  /*--- to files automatically after this routine. Note that the ---*/
14578  /*--- ordering of the data loading MUST match the order of the ---*/
14579  /*--- variable registration above for the files to be correct. ---*/
14580  /*--------------------------------------------------------------------------*/
14581 
14582  jPoint = 0;
14583 
14584  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
14585 
14586  /*--- Check for halos & write only if requested ---*/
14587 
14588  if (!Local_Halo[iPoint] || Wrt_Halo) {
14589 
14590  /*--- Restart the column index with each new point. ---*/
14591 
14592  iVar = 0;
14593 
14594  /*--- Load the grid node coordinate values. ---*/
14595 
14596  for (iDim = 0; iDim < geometry->GetnDim(); iDim++) {
14597  Local_Data[jPoint][iVar] = geometry->node[iPoint]->GetCoord(iDim);
14598  if (config->GetSystemMeasurements() == US)
14599  Local_Data[jPoint][iVar] *= 12.0;
14600  iVar++;
14601  }
14602 
14603  /*--- Load the conservative variable states for the mean flow variables.
14604  If requested, load the limiters and residuals as well. ---*/
14605 
14606  for (jVar = 0; jVar < nVar_First; jVar++) {
14607  Local_Data[jPoint][iVar] = solver[FirstIndex]->GetNodes()->GetSolution(iPoint, jVar);
14608  iVar++;
14609  }
14610 
14611  if (config->GetWrt_Residuals()) {
14612  for (jVar = 0; jVar < nVar_First; jVar++) {
14613  Local_Data[jPoint][iVar] = solver[FirstIndex]->LinSysRes.GetBlock(iPoint, jVar);
14614  iVar++;
14615  }
14616  }
14617 
14618 
14619  /*--- New variables can be loaded to the Local_Data structure here,
14620  assuming they were registered above correctly. ---*/
14621 
14622  /*--- Increment the point counter, as there may have been halos we
14623  skipped over during the data loading. ---*/
14624 
14625  jPoint++;
14626 
14627  }
14628  }
14629 
14630  /*--- Free memory for auxiliary vectors. ---*/
14631 
14632  delete [] Local_Halo;
14633 
14634 }
14635 
14636 void COutputLegacy::SortConnectivity(CConfig *config, CGeometry *geometry, unsigned short val_iZone) {
14637 
14638  /*--- Flags identifying the types of files to be written. ---*/
14639 
14640  bool Wrt_Vol = config->GetWrt_Vol_Sol();
14641  bool Wrt_Srf = config->GetWrt_Srf_Sol();
14642 
14643  /*--- Sort connectivity for each type of element (excluding halos). Note
14644  In these routines, we sort the connectivity into a linear partitioning
14645  across all processors based on the global index of the grid nodes. ---*/
14646 
14647  /*--- Sort volumetric grid connectivity. ---*/
14648 
14649  if (Wrt_Vol) {
14650 
14651  if ((rank == MASTER_NODE) && (size != SINGLE_NODE))
14652  cout <<"Sorting volumetric grid connectivity." << endl;
14653 
14654  SortVolumetricConnectivity(config, geometry, TRIANGLE );
14655  SortVolumetricConnectivity(config, geometry, QUADRILATERAL);
14656  SortVolumetricConnectivity(config, geometry, TETRAHEDRON );
14657  SortVolumetricConnectivity(config, geometry, HEXAHEDRON );
14658  SortVolumetricConnectivity(config, geometry, PRISM );
14659  SortVolumetricConnectivity(config, geometry, PYRAMID );
14660 
14661  }
14662 
14663  /*--- Sort surface grid connectivity. ---*/
14664 
14665  if (Wrt_Srf) {
14666 
14667  if ((rank == MASTER_NODE) && (size != SINGLE_NODE))
14668  cout <<"Sorting surface grid connectivity." << endl;
14669 
14670  SortSurfaceConnectivity(config, geometry, LINE );
14671  SortSurfaceConnectivity(config, geometry, TRIANGLE );
14672  SortSurfaceConnectivity(config, geometry, QUADRILATERAL);
14673 
14674  }
14675 
14676  /*--- Reduce the total number of cells we will be writing in the output files. ---*/
14677 
14678  unsigned long nTotal_Elem = nParallel_Tria + nParallel_Quad + nParallel_Tetr + nParallel_Hexa + nParallel_Pris + nParallel_Pyra;
14679  unsigned long nTotal_Surf_Elem = nParallel_Line + nParallel_BoundTria + nParallel_BoundQuad;
14680 #ifndef HAVE_MPI
14681  nGlobal_Elem_Par = nTotal_Elem;
14682  nSurf_Elem_Par = nTotal_Surf_Elem;
14683 #else
14684  SU2_MPI::Allreduce(&nTotal_Elem, &nGlobal_Elem_Par, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD);
14685  SU2_MPI::Allreduce(&nTotal_Surf_Elem, &nSurf_Elem_Par, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD);
14686 #endif
14687 
14688 }
14689 
14690 void COutputLegacy::SortVolumetricConnectivity(CConfig *config, CGeometry *geometry, unsigned short Elem_Type) {
14691 
14692  unsigned long iProcessor;
14693  unsigned short NODES_PER_ELEMENT = 0;
14694  unsigned long iPoint, jPoint, kPoint, nLocalPoint, nTotalPoint;
14695  unsigned long nElem_Total = 0, Global_Index;
14696 
14697  unsigned long iVertex, iMarker;
14698  int SendRecv, RecvFrom;
14699 
14700  bool notPeriodic, notHalo, addedPeriodic, isPeriodic;
14701 
14702  int *Local_Halo = NULL;
14703  int *Conn_Elem = NULL;
14704 
14705 #ifdef HAVE_MPI
14706  SU2_MPI::Request *send_req, *recv_req;
14707  SU2_MPI::Status status;
14708  int ind;
14709 #endif
14710 
14711  /*--- Store the local number of this element type and the number of nodes
14712  per this element type. In serial, this will be the total number of this
14713  element type in the entire mesh. In parallel, it is the number on only
14714  the current partition. ---*/
14715 
14716  switch (Elem_Type) {
14717  case TRIANGLE:
14718  NODES_PER_ELEMENT = N_POINTS_TRIANGLE;
14719  break;
14720  case QUADRILATERAL:
14721  NODES_PER_ELEMENT = N_POINTS_QUADRILATERAL;
14722  break;
14723  case TETRAHEDRON:
14724  NODES_PER_ELEMENT = N_POINTS_TETRAHEDRON;
14725  break;
14726  case HEXAHEDRON:
14727  NODES_PER_ELEMENT = N_POINTS_HEXAHEDRON;
14728  break;
14729  case PRISM:
14730  NODES_PER_ELEMENT = N_POINTS_PRISM;
14731  break;
14732  case PYRAMID:
14733  NODES_PER_ELEMENT = N_POINTS_PYRAMID;
14734  break;
14735  default:
14736  SU2_MPI::Error("Unrecognized element type", CURRENT_FUNCTION);
14737  }
14738 
14739  /*--- Force the removal of all added periodic elements (use global index).
14740  First, we isolate and create a list of all added periodic points, excluding
14741  those that were part of the original domain (we want these to be in the
14742  output files). ---*/
14743 
14744  vector<unsigned long> Added_Periodic;
14745  Added_Periodic.clear();
14746 
14747  if (config->GetKind_SU2() != SU2_DEF) {
14748  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
14749  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
14750  SendRecv = config->GetMarker_All_SendRecv(iMarker);
14751  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
14752  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
14753 
14754  if ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
14755  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 0) &&
14756  (SendRecv < 0)) {
14757  Added_Periodic.push_back(geometry->node[iPoint]->GetGlobalIndex());
14758  }
14759  }
14760  }
14761  }
14762  }
14763 
14764  /*--- Now we communicate this information to all processors, so that they
14765  can force the removal of these particular nodes by flagging them as halo
14766  points. In general, this should be a small percentage of the total mesh,
14767  so the communication/storage costs here shouldn't be prohibitive. ---*/
14768 
14769  /*--- First communicate the number of points that each rank has found. ---*/
14770 
14771  unsigned long nAddedPeriodic = 0, maxAddedPeriodic = 0;
14772  unsigned long Buffer_Send_nAddedPeriodic[1], *Buffer_Recv_nAddedPeriodic = NULL;
14773  Buffer_Recv_nAddedPeriodic = new unsigned long[size];
14774 
14775  nAddedPeriodic = Added_Periodic.size();
14776  Buffer_Send_nAddedPeriodic[0] = nAddedPeriodic;
14777 
14778 #ifdef HAVE_MPI
14779  SU2_MPI::Allreduce(&nAddedPeriodic, &maxAddedPeriodic, 1, MPI_UNSIGNED_LONG,
14781  SU2_MPI::Allgather(&Buffer_Send_nAddedPeriodic, 1, MPI_UNSIGNED_LONG,
14782  Buffer_Recv_nAddedPeriodic, 1, MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
14783 #else
14784  maxAddedPeriodic = nAddedPeriodic;
14785  Buffer_Recv_nAddedPeriodic[0] = Buffer_Send_nAddedPeriodic[0];
14786 #endif
14787 
14788  /*--- Communicate the global index values of all added periodic nodes. ---*/
14789  unsigned long *Buffer_Send_AddedPeriodic = new unsigned long[maxAddedPeriodic];
14790  unsigned long *Buffer_Recv_AddedPeriodic = new unsigned long[size*maxAddedPeriodic];
14791 
14792  for (iPoint = 0; iPoint < Added_Periodic.size(); iPoint++) {
14793  Buffer_Send_AddedPeriodic[iPoint] = Added_Periodic[iPoint];
14794  }
14795 
14796  /*--- Gather the element connectivity information. All processors will now
14797  have a copy of the global index values for all added periodic points. ---*/
14798 
14799 #ifdef HAVE_MPI
14800  SU2_MPI::Allgather(Buffer_Send_AddedPeriodic, maxAddedPeriodic, MPI_UNSIGNED_LONG,
14801  Buffer_Recv_AddedPeriodic, maxAddedPeriodic, MPI_UNSIGNED_LONG,
14802  MPI_COMM_WORLD);
14803 #else
14804  for (iPoint = 0; iPoint < maxAddedPeriodic; iPoint++)
14805  Buffer_Recv_AddedPeriodic[iPoint] = Buffer_Send_AddedPeriodic[iPoint];
14806 #endif
14807 
14808  /*--- Search all send/recv boundaries on this partition for halo cells. In
14809  particular, consider only the recv conditions (these are the true halo
14810  nodes). Check the ranks of the processors that are communicating and
14811  choose to keep only the halo cells from the higher rank processor. Here,
14812  we are also choosing to keep periodic nodes that were part of the original
14813  domain. We will check the communicated list of added periodic points. ---*/
14814 
14815  Local_Halo = new int[geometry->GetnPoint()];
14816  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
14817  Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain();
14818 
14819  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
14820  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
14821  SendRecv = config->GetMarker_All_SendRecv(iMarker);
14822  RecvFrom = abs(SendRecv)-1;
14823 
14824  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
14825  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
14826  Global_Index = geometry->node[iPoint]->GetGlobalIndex();
14827 
14828  /*--- We need to keep one copy of overlapping halo cells. ---*/
14829 
14830  notHalo = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() == 0) &&
14831  (SendRecv < 0) && (rank > RecvFrom));
14832 
14833  /*--- We want to keep the periodic nodes that were part of the original domain.
14834  For SU2_DEF we want to keep all periodic nodes. ---*/
14835 
14836  if (config->GetKind_SU2() == SU2_DEF) {
14837  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0));
14838  }else {
14839  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
14840  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1));
14841  }
14842 
14843  notPeriodic = (isPeriodic && (SendRecv < 0));
14844 
14845  /*--- Lastly, check that this isn't an added periodic point that
14846  we will forcibly remove. Use the communicated list of these points. ---*/
14847 
14848  addedPeriodic = false; kPoint = 0;
14849  for (iProcessor = 0; iProcessor < (unsigned long)size; iProcessor++) {
14850  for (jPoint = 0; jPoint < Buffer_Recv_nAddedPeriodic[iProcessor]; jPoint++) {
14851  if (Global_Index == Buffer_Recv_AddedPeriodic[kPoint+jPoint])
14852  addedPeriodic = true;
14853  }
14854 
14855  /*--- Adjust jNode to index of next proc's data in the buffers. ---*/
14856 
14857  kPoint = (iProcessor+1)*maxAddedPeriodic;
14858 
14859  }
14860 
14861  /*--- If we found either of these types of nodes, flag them to be kept. ---*/
14862 
14863  if ((notHalo || notPeriodic) && !addedPeriodic) {
14864  Local_Halo[iPoint] = false;
14865  }
14866 
14867  }
14868  }
14869  }
14870 
14871  /*--- Now that we've done the gymnastics to find any periodic points,
14872  compute the total number of local and global points for the output. ---*/
14873 
14874  nLocalPoint = 0;
14875  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
14876  if (Local_Halo[iPoint] == false)
14877  nLocalPoint++;
14878 
14879 #ifdef HAVE_MPI
14880  SU2_MPI::Allreduce(&nLocalPoint, &nTotalPoint, 1,
14882 #else
14883  nTotalPoint = nLocalPoint;
14884 #endif
14885 
14886  /*--- Compute the number of points that will be on each processor.
14887  This is a linear partitioning with the addition of a simple load
14888  balancing for any remainder points. ---*/
14889 
14890  unsigned long *npoint_procs = new unsigned long[size];
14891  unsigned long *starting_node = new unsigned long[size];
14892  unsigned long *ending_node = new unsigned long[size];
14893  unsigned long *nPoint_Linear = new unsigned long[size+1];
14894 
14895  unsigned long total_pt_accounted = 0;
14896  for (int ii = 0; ii < size; ii++) {
14897  npoint_procs[ii] = nTotalPoint/size;
14898  total_pt_accounted = total_pt_accounted + npoint_procs[ii];
14899  }
14900 
14901  /*--- Get the number of remainder points after the even division. ---*/
14902 
14903  unsigned long rem_points = nTotalPoint-total_pt_accounted;
14904  for (unsigned long ii = 0; ii < rem_points; ii++) {
14905  npoint_procs[ii]++;
14906  }
14907 
14908  /*--- Store the local number of nodes and the beginning/end index ---*/
14909 
14910  starting_node[0] = 0;
14911  ending_node[0] = starting_node[0] + npoint_procs[0];
14912  nPoint_Linear[0] = 0;
14913  for (int ii = 1; ii < size; ii++) {
14914  starting_node[ii] = ending_node[ii-1];
14915  ending_node[ii] = starting_node[ii] + npoint_procs[ii];
14916  nPoint_Linear[ii] = nPoint_Linear[ii-1] + npoint_procs[ii-1];
14917  }
14918  nPoint_Linear[size] = nTotalPoint;
14919 
14920  /*--- We start with the connectivity distributed across all procs with
14921  no particular ordering assumed. We need to loop through our local partition
14922  and decide how many elements we must send to each other rank in order to
14923  have all elements sorted according to a linear partitioning of the grid
14924  nodes, i.e., rank 0 holds the first nPoint()/nProcessors nodes.
14925  First, initialize a counter and flag. ---*/
14926 
14927  int *nElem_Send = new int[size+1]; nElem_Send[0] = 0;
14928  int *nElem_Recv = new int[size+1]; nElem_Recv[0] = 0;
14929  int *nElem_Flag = new int[size];
14930 
14931  for (int ii=0; ii < size; ii++) {
14932  nElem_Send[ii] = 0;
14933  nElem_Recv[ii] = 0;
14934  nElem_Flag[ii]= -1;
14935  }
14936  nElem_Send[size] = 0; nElem_Recv[size] = 0;
14937 
14938  for (int ii = 0; ii < (int)geometry->GetnElem(); ii++ ) {
14939  if (geometry->elem[ii]->GetVTK_Type() == Elem_Type) {
14940  for ( int jj = 0; jj < NODES_PER_ELEMENT; jj++ ) {
14941 
14942  /*--- Get the index of the current point. ---*/
14943 
14944  iPoint = geometry->elem[ii]->GetNode(jj);
14945  Global_Index = geometry->node[iPoint]->GetGlobalIndex();
14946 
14947  /*--- Search for the lowest global index in this element. We
14948  send the element to the processor owning the range that includes
14949  the lowest global index value. ---*/
14950 
14951  for (int kk = 0; kk < NODES_PER_ELEMENT; kk++) {
14952  jPoint = geometry->elem[ii]->GetNode(kk);
14953  unsigned long newID = geometry->node[jPoint]->GetGlobalIndex();
14954  if (newID < Global_Index) Global_Index = newID;
14955  }
14956 
14957  /*--- Search for the processor that owns this point ---*/
14958 
14959  iProcessor = Global_Index/npoint_procs[0];
14960  if (iProcessor >= (unsigned long)size)
14961  iProcessor = (unsigned long)size-1;
14962  if (Global_Index >= nPoint_Linear[iProcessor])
14963  while(Global_Index >= nPoint_Linear[iProcessor+1]) iProcessor++;
14964  else
14965  while(Global_Index < nPoint_Linear[iProcessor]) iProcessor--;
14966 
14967  /*--- If we have not visited this element yet, increment our
14968  number of elements that must be sent to a particular proc. ---*/
14969 
14970  if ((nElem_Flag[iProcessor] != ii)) {
14971  nElem_Flag[iProcessor] = ii;
14972  nElem_Send[iProcessor+1]++;
14973  }
14974 
14975  }
14976  }
14977  }
14978 
14979  /*--- Communicate the number of cells to be sent/recv'd amongst
14980  all processors. After this communication, each proc knows how
14981  many cells it will receive from each other processor. ---*/
14982 
14983 #ifdef HAVE_MPI
14984  SU2_MPI::Alltoall(&(nElem_Send[1]), 1, MPI_INT,
14985  &(nElem_Recv[1]), 1, MPI_INT, MPI_COMM_WORLD);
14986 #else
14987  nElem_Recv[1] = nElem_Send[1];
14988 #endif
14989 
14990  /*--- Prepare to send connectivities. First check how many
14991  messages we will be sending and receiving. Here we also put
14992  the counters into cumulative storage format to make the
14993  communications simpler. ---*/
14994 
14995  int nSends = 0, nRecvs = 0;
14996  for (int ii=0; ii < size; ii++) nElem_Flag[ii] = -1;
14997 
14998  for (int ii = 0; ii < size; ii++) {
14999  if ((ii != rank) && (nElem_Send[ii+1] > 0)) nSends++;
15000  if ((ii != rank) && (nElem_Recv[ii+1] > 0)) nRecvs++;
15001 
15002  nElem_Send[ii+1] += nElem_Send[ii];
15003  nElem_Recv[ii+1] += nElem_Recv[ii];
15004  }
15005 
15006  /*--- Allocate memory to hold the connectivity that we are
15007  sending. ---*/
15008 
15009  unsigned long *connSend = NULL;
15010  connSend = new unsigned long[NODES_PER_ELEMENT*nElem_Send[size]];
15011  for (int ii = 0; ii < NODES_PER_ELEMENT*nElem_Send[size]; ii++)
15012  connSend[ii] = 0;
15013 
15014  /*--- Allocate arrays for storing halo flags. ---*/
15015 
15016  unsigned short *haloSend = new unsigned short[nElem_Send[size]];
15017  for (int ii = 0; ii < nElem_Send[size]; ii++)
15018  haloSend[ii] = false;
15019 
15020  /*--- Create an index variable to keep track of our index
15021  position as we load up the send buffer. ---*/
15022 
15023  unsigned long *index = new unsigned long[size];
15024  for (int ii=0; ii < size; ii++) index[ii] = NODES_PER_ELEMENT*nElem_Send[ii];
15025 
15026  unsigned long *haloIndex = new unsigned long[size];
15027  for (int ii=0; ii < size; ii++) haloIndex[ii] = nElem_Send[ii];
15028 
15029  /*--- Loop through our elements and load the elems and their
15030  additional data that we will send to the other procs. ---*/
15031 
15032  for (int ii = 0; ii < (int)geometry->GetnElem(); ii++) {
15033  if (geometry->elem[ii]->GetVTK_Type() == Elem_Type) {
15034  for ( int jj = 0; jj < NODES_PER_ELEMENT; jj++ ) {
15035 
15036  /*--- Get the index of the current point. ---*/
15037 
15038  iPoint = geometry->elem[ii]->GetNode(jj);
15039  Global_Index = geometry->node[iPoint]->GetGlobalIndex();
15040 
15041  /*--- Search for the lowest global index in this element. We
15042  send the element to the processor owning the range that includes
15043  the lowest global index value. ---*/
15044 
15045  for (int kk = 0; kk < NODES_PER_ELEMENT; kk++) {
15046  jPoint = geometry->elem[ii]->GetNode(kk);
15047  unsigned long newID = geometry->node[jPoint]->GetGlobalIndex();
15048  if (newID < Global_Index) Global_Index = newID;
15049  }
15050 
15051  /*--- Search for the processor that owns this point ---*/
15052 
15053  iProcessor = Global_Index/npoint_procs[0];
15054  if (iProcessor >= (unsigned long)size)
15055  iProcessor = (unsigned long)size-1;
15056  if (Global_Index >= nPoint_Linear[iProcessor])
15057  while(Global_Index >= nPoint_Linear[iProcessor+1]) iProcessor++;
15058  else
15059  while(Global_Index < nPoint_Linear[iProcessor]) iProcessor--;
15060 
15061  /*--- Load connectivity into the buffer for sending ---*/
15062 
15063  if (nElem_Flag[iProcessor] != ii) {
15064 
15065  nElem_Flag[iProcessor] = ii;
15066  unsigned long nn = index[iProcessor];
15067  unsigned long mm = haloIndex[iProcessor];
15068 
15069  /*--- Load the connectivity values. ---*/
15070 
15071  for (int kk = 0; kk < NODES_PER_ELEMENT; kk++) {
15072  iPoint = geometry->elem[ii]->GetNode(kk);
15073  connSend[nn] = geometry->node[iPoint]->GetGlobalIndex(); nn++;
15074 
15075  /*--- Check if this is a halo node. If so, flag this element
15076  as a halo cell. We will use this later to sort and remove
15077  any duplicates from the connectivity list. ---*/
15078 
15079  if (Local_Halo[iPoint]) haloSend[mm] = true;
15080 
15081  }
15082 
15083  /*--- Increment the index by the message length ---*/
15084 
15085  index[iProcessor] += NODES_PER_ELEMENT;
15086  haloIndex[iProcessor]++;
15087 
15088  }
15089  }
15090  }
15091  }
15092 
15093  /*--- Free memory after loading up the send buffer. ---*/
15094 
15095  delete [] index;
15096  delete [] haloIndex;
15097 
15098  /*--- Allocate the memory that we need for receiving the conn
15099  values and then cue up the non-blocking receives. Note that
15100  we do not include our own rank in the communications. We will
15101  directly copy our own data later. ---*/
15102 
15103  unsigned long *connRecv = NULL;
15104  connRecv = new unsigned long[NODES_PER_ELEMENT*nElem_Recv[size]];
15105  for (int ii = 0; ii < NODES_PER_ELEMENT*nElem_Recv[size]; ii++)
15106  connRecv[ii] = 0;
15107 
15108  unsigned short *haloRecv = new unsigned short[nElem_Recv[size]];
15109  for (int ii = 0; ii < nElem_Recv[size]; ii++)
15110  haloRecv[ii] = false;
15111 
15112 #ifdef HAVE_MPI
15113  /*--- We need double the number of messages to send both the conn.
15114  and the flags for the halo cells. ---*/
15115 
15116  send_req = new SU2_MPI::Request[2*nSends];
15117  recv_req = new SU2_MPI::Request[2*nRecvs];
15118 
15119  /*--- Launch the non-blocking recv's for the connectivity. ---*/
15120 
15121  unsigned long iMessage = 0;
15122  for (int ii=0; ii<size; ii++) {
15123  if ((ii != rank) && (nElem_Recv[ii+1] > nElem_Recv[ii])) {
15124  int ll = NODES_PER_ELEMENT*nElem_Recv[ii];
15125  int kk = nElem_Recv[ii+1] - nElem_Recv[ii];
15126  int count = NODES_PER_ELEMENT*kk;
15127  int source = ii;
15128  int tag = ii + 1;
15129  SU2_MPI::Irecv(&(connRecv[ll]), count, MPI_UNSIGNED_LONG, source, tag,
15130  MPI_COMM_WORLD, &(recv_req[iMessage]));
15131  iMessage++;
15132  }
15133  }
15134 
15135  /*--- Launch the non-blocking sends of the connectivity. ---*/
15136 
15137  iMessage = 0;
15138  for (int ii=0; ii<size; ii++) {
15139  if ((ii != rank) && (nElem_Send[ii+1] > nElem_Send[ii])) {
15140  int ll = NODES_PER_ELEMENT*nElem_Send[ii];
15141  int kk = nElem_Send[ii+1] - nElem_Send[ii];
15142  int count = NODES_PER_ELEMENT*kk;
15143  int dest = ii;
15144  int tag = rank + 1;
15145  SU2_MPI::Isend(&(connSend[ll]), count, MPI_UNSIGNED_LONG, dest, tag,
15146  MPI_COMM_WORLD, &(send_req[iMessage]));
15147  iMessage++;
15148  }
15149  }
15150 
15151  /*--- Repeat the process to communicate the halo flags. ---*/
15152 
15153  iMessage = 0;
15154  for (int ii=0; ii<size; ii++) {
15155  if ((ii != rank) && (nElem_Recv[ii+1] > nElem_Recv[ii])) {
15156  int ll = nElem_Recv[ii];
15157  int kk = nElem_Recv[ii+1] - nElem_Recv[ii];
15158  int count = kk;
15159  int source = ii;
15160  int tag = ii + 1;
15161  SU2_MPI::Irecv(&(haloRecv[ll]), count, MPI_UNSIGNED_SHORT, source, tag,
15162  MPI_COMM_WORLD, &(recv_req[iMessage+nRecvs]));
15163  iMessage++;
15164  }
15165  }
15166 
15167  /*--- Launch the non-blocking sends of the halo flags. ---*/
15168 
15169  iMessage = 0;
15170  for (int ii=0; ii<size; ii++) {
15171  if ((ii != rank) && (nElem_Send[ii+1] > nElem_Send[ii])) {
15172  int ll = nElem_Send[ii];
15173  int kk = nElem_Send[ii+1] - nElem_Send[ii];
15174  int count = kk;
15175  int dest = ii;
15176  int tag = rank + 1;
15177  SU2_MPI::Isend(&(haloSend[ll]), count, MPI_UNSIGNED_SHORT, dest, tag,
15178  MPI_COMM_WORLD, &(send_req[iMessage+nSends]));
15179  iMessage++;
15180  }
15181  }
15182 #endif
15183 
15184  /*--- Copy my own rank's data into the recv buffer directly. ---*/
15185 
15186  int mm = NODES_PER_ELEMENT*nElem_Recv[rank];
15187  int ll = NODES_PER_ELEMENT*nElem_Send[rank];
15188  int kk = NODES_PER_ELEMENT*nElem_Send[rank+1];
15189 
15190  for (int nn=ll; nn<kk; nn++, mm++) connRecv[mm] = connSend[nn];
15191 
15192  mm = nElem_Recv[rank];
15193  ll = nElem_Send[rank];
15194  kk = nElem_Send[rank+1];
15195 
15196  for (int nn=ll; nn<kk; nn++, mm++) haloRecv[mm] = haloSend[nn];
15197 
15198  /*--- Wait for the non-blocking sends and recvs to complete. ---*/
15199 
15200 #ifdef HAVE_MPI
15201  int number = 2*nSends;
15202  for (int ii = 0; ii < number; ii++)
15203  SU2_MPI::Waitany(number, send_req, &ind, &status);
15204 
15205  number = 2*nRecvs;
15206  for (int ii = 0; ii < number; ii++)
15207  SU2_MPI::Waitany(number, recv_req, &ind, &status);
15208 
15209  delete [] send_req;
15210  delete [] recv_req;
15211 #endif
15212 
15213  /*--- Store the connectivity for this rank in the proper data
15214  structure before post-processing below. Note that we add 1 here
15215  to the connectivity for vizualization packages. First, allocate
15216  appropriate amount of memory for this section. ---*/
15217 
15218  if (nElem_Recv[size] > 0) Conn_Elem = new int[NODES_PER_ELEMENT*nElem_Recv[size]];
15219  int count = 0; nElem_Total = 0;
15220  for (int ii = 0; ii < nElem_Recv[size]; ii++) {
15221  if (!haloRecv[ii]) {
15222  nElem_Total++;
15223  for (int jj = 0; jj < NODES_PER_ELEMENT; jj++) {
15224  Conn_Elem[count] = (int)connRecv[ii*NODES_PER_ELEMENT+jj] + 1;
15225  count++;
15226  }
15227  }
15228  }
15229 
15230  /*--- Store the particular global element count in the class data,
15231  and set the class data pointer to the connectivity array. ---*/
15232 
15233  switch (Elem_Type) {
15234  case TRIANGLE:
15235  nParallel_Tria = nElem_Total;
15236  if (nParallel_Tria > 0) Conn_Tria_Par = Conn_Elem;
15237  break;
15238  case QUADRILATERAL:
15239  nParallel_Quad = nElem_Total;
15240  if (nParallel_Quad > 0) Conn_Quad_Par = Conn_Elem;
15241  break;
15242  case TETRAHEDRON:
15243  nParallel_Tetr = nElem_Total;
15244  if (nParallel_Tetr > 0) Conn_Tetr_Par = Conn_Elem;
15245  break;
15246  case HEXAHEDRON:
15247  nParallel_Hexa = nElem_Total;
15248  if (nParallel_Hexa > 0) Conn_Hexa_Par = Conn_Elem;
15249  break;
15250  case PRISM:
15251  nParallel_Pris = nElem_Total;
15252  if (nParallel_Pris > 0) Conn_Pris_Par = Conn_Elem;
15253  break;
15254  case PYRAMID:
15255  nParallel_Pyra = nElem_Total;
15256  if (nParallel_Pyra > 0) Conn_Pyra_Par = Conn_Elem;
15257  break;
15258  default:
15259  SU2_MPI::Error("Unrecognized element type", CURRENT_FUNCTION);
15260  break;
15261  }
15262 
15263  /*--- Free temporary memory from communications ---*/
15264 
15265  delete [] connSend;
15266  delete [] connRecv;
15267  delete [] haloSend;
15268  delete [] haloRecv;
15269  delete [] Local_Halo;
15270  delete [] nElem_Recv;
15271  delete [] nElem_Send;
15272  delete [] nElem_Flag;
15273  delete [] Buffer_Recv_nAddedPeriodic;
15274  delete [] Buffer_Send_AddedPeriodic;
15275  delete [] Buffer_Recv_AddedPeriodic;
15276  delete [] npoint_procs;
15277  delete [] starting_node;
15278  delete [] ending_node;
15279  delete [] nPoint_Linear;
15280 
15281 }
15282 
15283 void COutputLegacy::SortSurfaceConnectivity(CConfig *config, CGeometry *geometry, unsigned short Elem_Type) {
15284 
15285  unsigned long iProcessor;
15286  unsigned short NODES_PER_ELEMENT;
15287  unsigned long iPoint, jPoint, kPoint, nLocalPoint, nTotalPoint;
15288  unsigned long nElem_Total = 0, Global_Index;
15289 
15290  unsigned long iVertex, iMarker;
15291  int SendRecv, RecvFrom;
15292 
15293  bool notPeriodic, notHalo, addedPeriodic, isPeriodic;
15294 
15295  int *Local_Halo = NULL;
15296  int *Conn_Elem = NULL;
15297 
15298 #ifdef HAVE_MPI
15299  SU2_MPI::Request *send_req, *recv_req;
15300  SU2_MPI::Status status;
15301  int ind;
15302 #endif
15303 
15304  /*--- Store the local number of this element type and the number of nodes
15305  per this element type. In serial, this will be the total number of this
15306  element type in the entire mesh. In parallel, it is the number on only
15307  the current partition. ---*/
15308 
15309  switch (Elem_Type) {
15310  case LINE:
15311  NODES_PER_ELEMENT = N_POINTS_LINE;
15312  break;
15313  case TRIANGLE:
15314  NODES_PER_ELEMENT = N_POINTS_TRIANGLE;
15315  break;
15316  case QUADRILATERAL:
15317  NODES_PER_ELEMENT = N_POINTS_QUADRILATERAL;
15318  break;
15319  default:
15320  SU2_MPI::Error("Unrecognized element type", CURRENT_FUNCTION);
15321  NODES_PER_ELEMENT = 0;
15322  break;
15323  }
15324 
15325  /*--- Force the removal of all added periodic elements (use global index).
15326  First, we isolate and create a list of all added periodic points, excluding
15327  those that were part of the original domain (we want these to be in the
15328  output files). ---*/
15329 
15330  vector<unsigned long> Added_Periodic;
15331  Added_Periodic.clear();
15332 
15333  if (config->GetKind_SU2() != SU2_DEF) {
15334  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
15335  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
15336  SendRecv = config->GetMarker_All_SendRecv(iMarker);
15337  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
15338  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
15339 
15340  if ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
15341  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 0) &&
15342  (SendRecv < 0)) {
15343  Added_Periodic.push_back(geometry->node[iPoint]->GetGlobalIndex());
15344  }
15345  }
15346  }
15347  }
15348  }
15349 
15350  /*--- Now we communicate this information to all processors, so that they
15351  can force the removal of these particular nodes by flagging them as halo
15352  points. In general, this should be a small percentage of the total mesh,
15353  so the communication/storage costs here shouldn't be prohibitive. ---*/
15354 
15355  /*--- First communicate the number of points that each rank has found. ---*/
15356 
15357  unsigned long nAddedPeriodic = 0, maxAddedPeriodic = 0;
15358  unsigned long Buffer_Send_nAddedPeriodic[1], *Buffer_Recv_nAddedPeriodic = NULL;
15359  Buffer_Recv_nAddedPeriodic = new unsigned long[size];
15360 
15361  nAddedPeriodic = Added_Periodic.size();
15362  Buffer_Send_nAddedPeriodic[0] = nAddedPeriodic;
15363 
15364 #ifdef HAVE_MPI
15365  SU2_MPI::Allreduce(&nAddedPeriodic, &maxAddedPeriodic, 1, MPI_UNSIGNED_LONG,
15367  SU2_MPI::Allgather(&Buffer_Send_nAddedPeriodic, 1, MPI_UNSIGNED_LONG,
15368  Buffer_Recv_nAddedPeriodic, 1, MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
15369 #else
15370  maxAddedPeriodic = nAddedPeriodic;
15371  Buffer_Recv_nAddedPeriodic[0] = Buffer_Send_nAddedPeriodic[0];
15372 #endif
15373 
15374  /*--- Communicate the global index values of all added periodic nodes. ---*/
15375  unsigned long *Buffer_Send_AddedPeriodic = new unsigned long[maxAddedPeriodic];
15376  unsigned long *Buffer_Recv_AddedPeriodic = new unsigned long[size*maxAddedPeriodic];
15377 
15378  for (iPoint = 0; iPoint < Added_Periodic.size(); iPoint++) {
15379  Buffer_Send_AddedPeriodic[iPoint] = Added_Periodic[iPoint];
15380  }
15381 
15382  /*--- Gather the element connectivity information. All processors will now
15383  have a copy of the global index values for all added periodic points. ---*/
15384 
15385 #ifdef HAVE_MPI
15386  SU2_MPI::Allgather(Buffer_Send_AddedPeriodic, maxAddedPeriodic, MPI_UNSIGNED_LONG,
15387  Buffer_Recv_AddedPeriodic, maxAddedPeriodic, MPI_UNSIGNED_LONG,
15388  MPI_COMM_WORLD);
15389 #else
15390  for (iPoint = 0; iPoint < maxAddedPeriodic; iPoint++)
15391  Buffer_Recv_AddedPeriodic[iPoint] = Buffer_Send_AddedPeriodic[iPoint];
15392 #endif
15393 
15394  /*--- Search all send/recv boundaries on this partition for halo cells. In
15395  particular, consider only the recv conditions (these are the true halo
15396  nodes). Check the ranks of the processors that are communicating and
15397  choose to keep only the halo cells from the higher rank processor. Here,
15398  we are also choosing to keep periodic nodes that were part of the original
15399  domain. We will check the communicated list of added periodic points. ---*/
15400 
15401  Local_Halo = new int[geometry->GetnPoint()];
15402  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
15403  Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain();
15404 
15405  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
15406  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
15407  SendRecv = config->GetMarker_All_SendRecv(iMarker);
15408  RecvFrom = abs(SendRecv)-1;
15409 
15410  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
15411  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
15412  Global_Index = geometry->node[iPoint]->GetGlobalIndex();
15413 
15414  /*--- We need to keep one copy of overlapping halo cells. ---*/
15415 
15416  notHalo = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() == 0) &&
15417  (SendRecv < 0) && (rank > RecvFrom));
15418 
15419  /*--- We want to keep the periodic nodes that were part of the original domain.
15420  For SU2_DEF we want to keep all periodic nodes. ---*/
15421 
15422  if (config->GetKind_SU2() == SU2_DEF) {
15423  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0));
15424  }else {
15425  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
15426  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1));
15427  }
15428 
15429  notPeriodic = (isPeriodic && (SendRecv < 0));
15430 
15431  /*--- Lastly, check that this isn't an added periodic point that
15432  we will forcibly remove. Use the communicated list of these points. ---*/
15433 
15434  addedPeriodic = false; kPoint = 0;
15435  for (iProcessor = 0; iProcessor < (unsigned long)size; iProcessor++) {
15436  for (jPoint = 0; jPoint < Buffer_Recv_nAddedPeriodic[iProcessor]; jPoint++) {
15437  if (Global_Index == Buffer_Recv_AddedPeriodic[kPoint+jPoint])
15438  addedPeriodic = true;
15439  }
15440 
15441  /*--- Adjust jNode to index of next proc's data in the buffers. ---*/
15442 
15443  kPoint = (iProcessor+1)*maxAddedPeriodic;
15444 
15445  }
15446 
15447  /*--- If we found either of these types of nodes, flag them to be kept. ---*/
15448 
15449  if ((notHalo || notPeriodic) && !addedPeriodic) {
15450  Local_Halo[iPoint] = false;
15451  }
15452 
15453  }
15454  }
15455  }
15456 
15457  /*--- Now that we've done the gymnastics to find any periodic points,
15458  compute the total number of local and global points for the output. ---*/
15459 
15460  nLocalPoint = 0;
15461  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
15462  if (Local_Halo[iPoint] == false)
15463  nLocalPoint++;
15464 
15465 #ifdef HAVE_MPI
15466  SU2_MPI::Allreduce(&nLocalPoint, &nTotalPoint, 1,
15468 #else
15469  nTotalPoint = nLocalPoint;
15470 #endif
15471 
15472  /*--- Compute the number of points that will be on each processor.
15473  This is a linear partitioning with the addition of a simple load
15474  balancing for any remainder points. ---*/
15475 
15476  unsigned long *npoint_procs = new unsigned long[size];
15477  unsigned long *starting_node = new unsigned long[size];
15478  unsigned long *ending_node = new unsigned long[size];
15479  unsigned long *nPoint_Linear = new unsigned long[size+1];
15480 
15481  unsigned long total_pt_accounted = 0;
15482  for (int ii = 0; ii < size; ii++) {
15483  npoint_procs[ii] = nTotalPoint/size;
15484  total_pt_accounted = total_pt_accounted + npoint_procs[ii];
15485  }
15486 
15487  /*--- Get the number of remainder points after the even division. ---*/
15488 
15489  unsigned long rem_points = nTotalPoint-total_pt_accounted;
15490  for (unsigned long ii = 0; ii < rem_points; ii++) {
15491  npoint_procs[ii]++;
15492  }
15493 
15494  /*--- Store the local number of nodes and the beginning/end index ---*/
15495 
15496  starting_node[0] = 0;
15497  ending_node[0] = starting_node[0] + npoint_procs[0];
15498  nPoint_Linear[0] = 0;
15499  for (int ii = 1; ii < size; ii++) {
15500  starting_node[ii] = ending_node[ii-1];
15501  ending_node[ii] = starting_node[ii] + npoint_procs[ii];
15502  nPoint_Linear[ii] = nPoint_Linear[ii-1] + npoint_procs[ii-1];
15503  }
15504  nPoint_Linear[size] = nTotalPoint;
15505 
15506  /*--- We start with the connectivity distributed across all procs with
15507  no particular ordering assumed. We need to loop through our local partition
15508  and decide how many elements we must send to each other rank in order to
15509  have all elements sorted according to a linear partitioning of the grid
15510  nodes, i.e., rank 0 holds the first nPoint()/nProcessors nodes.
15511  First, initialize a counter and flag. ---*/
15512 
15513  int *nElem_Send = new int[size+1]; nElem_Send[0] = 0;
15514  int *nElem_Recv = new int[size+1]; nElem_Recv[0] = 0;
15515  int *nElem_Flag = new int[size];
15516 
15517  for (int ii=0; ii < size; ii++) {
15518  nElem_Send[ii] = 0;
15519  nElem_Recv[ii] = 0;
15520  nElem_Flag[ii]= -1;
15521  }
15522  nElem_Send[size] = 0; nElem_Recv[size] = 0;
15523 
15524  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
15525  if (config->GetMarker_All_Plotting(iMarker) == YES) {
15526 
15527  for (int ii = 0; ii < (int)geometry->GetnElem_Bound(iMarker); ii++) {
15528 
15529  if (geometry->bound[iMarker][ii]->GetVTK_Type() == Elem_Type) {
15530  for ( int jj = 0; jj < NODES_PER_ELEMENT; jj++ ) {
15531 
15532  /*--- Get the index of the current point. ---*/
15533 
15534  iPoint = geometry->bound[iMarker][ii]->GetNode(jj);
15535  Global_Index = geometry->node[iPoint]->GetGlobalIndex();
15536 
15537  /*--- Search for the lowest global index in this element. We
15538  send the element to the processor owning the range that includes
15539  the lowest global index value. ---*/
15540 
15541  for (int kk = 0; kk < NODES_PER_ELEMENT; kk++) {
15542  jPoint = geometry->bound[iMarker][ii]->GetNode(kk);
15543  unsigned long newID = geometry->node[jPoint]->GetGlobalIndex();
15544  if (newID < Global_Index) Global_Index = newID;
15545  }
15546 
15547  /*--- Search for the processor that owns this point ---*/
15548 
15549  iProcessor = Global_Index/npoint_procs[0];
15550  if (iProcessor >= (unsigned long)size)
15551  iProcessor = (unsigned long)size-1;
15552  if (Global_Index >= nPoint_Linear[iProcessor])
15553  while(Global_Index >= nPoint_Linear[iProcessor+1]) iProcessor++;
15554  else
15555  while(Global_Index < nPoint_Linear[iProcessor]) iProcessor--;
15556 
15557  /*--- If we have not visited this element yet, increment our
15558  number of elements that must be sent to a particular proc. ---*/
15559 
15560  if ((nElem_Flag[iProcessor] != ii)) {
15561  nElem_Flag[iProcessor] = ii;
15562  nElem_Send[iProcessor+1]++;
15563  }
15564 
15565  }
15566  }
15567  }
15568  }
15569  }
15570 
15571  /*--- Communicate the number of cells to be sent/recv'd amongst
15572  all processors. After this communication, each proc knows how
15573  many cells it will receive from each other processor. ---*/
15574 
15575 #ifdef HAVE_MPI
15576  SU2_MPI::Alltoall(&(nElem_Send[1]), 1, MPI_INT,
15577  &(nElem_Recv[1]), 1, MPI_INT, MPI_COMM_WORLD);
15578 #else
15579  nElem_Recv[1] = nElem_Send[1];
15580 #endif
15581 
15582  /*--- Prepare to send connectivities. First check how many
15583  messages we will be sending and receiving. Here we also put
15584  the counters into cumulative storage format to make the
15585  communications simpler. ---*/
15586 
15587  int nSends = 0, nRecvs = 0;
15588  for (int ii=0; ii < size; ii++) nElem_Flag[ii] = -1;
15589 
15590  for (int ii = 0; ii < size; ii++) {
15591  if ((ii != rank) && (nElem_Send[ii+1] > 0)) nSends++;
15592  if ((ii != rank) && (nElem_Recv[ii+1] > 0)) nRecvs++;
15593 
15594  nElem_Send[ii+1] += nElem_Send[ii];
15595  nElem_Recv[ii+1] += nElem_Recv[ii];
15596  }
15597 
15598  /*--- Allocate memory to hold the connectivity that we are
15599  sending. ---*/
15600 
15601  unsigned long *connSend = NULL;
15602  connSend = new unsigned long[NODES_PER_ELEMENT*nElem_Send[size]];
15603  for (int ii = 0; ii < NODES_PER_ELEMENT*nElem_Send[size]; ii++)
15604  connSend[ii] = 0;
15605 
15606  /*--- Allocate arrays for storing halo flags. ---*/
15607 
15608  unsigned short *haloSend = new unsigned short[nElem_Send[size]];
15609  for (int ii = 0; ii < nElem_Send[size]; ii++)
15610  haloSend[ii] = false;
15611 
15612  /*--- Create an index variable to keep track of our index
15613  position as we load up the send buffer. ---*/
15614 
15615  unsigned long *index = new unsigned long[size];
15616  for (int ii=0; ii < size; ii++) index[ii] = NODES_PER_ELEMENT*nElem_Send[ii];
15617 
15618  unsigned long *haloIndex = new unsigned long[size];
15619  for (int ii=0; ii < size; ii++) haloIndex[ii] = nElem_Send[ii];
15620 
15621  /*--- Loop through our elements and load the elems and their
15622  additional data that we will send to the other procs. ---*/
15623 
15624  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
15625  if (config->GetMarker_All_Plotting(iMarker) == YES) {
15626 
15627  for (int ii = 0; ii < (int)geometry->GetnElem_Bound(iMarker); ii++) {
15628 
15629  if (geometry->bound[iMarker][ii]->GetVTK_Type() == Elem_Type) {
15630  for ( int jj = 0; jj < NODES_PER_ELEMENT; jj++ ) {
15631 
15632  /*--- Get the index of the current point. ---*/
15633 
15634  iPoint = geometry->bound[iMarker][ii]->GetNode(jj);
15635  Global_Index = geometry->node[iPoint]->GetGlobalIndex();
15636 
15637  /*--- Search for the lowest global index in this element. We
15638  send the element to the processor owning the range that includes
15639  the lowest global index value. ---*/
15640 
15641  for (int kk = 0; kk < NODES_PER_ELEMENT; kk++) {
15642  jPoint = geometry->bound[iMarker][ii]->GetNode(kk);
15643  unsigned long newID = geometry->node[jPoint]->GetGlobalIndex();
15644  if (newID < Global_Index) Global_Index = newID;
15645  }
15646 
15647  /*--- Search for the processor that owns this point ---*/
15648 
15649  iProcessor = Global_Index/npoint_procs[0];
15650  if (iProcessor >= (unsigned long)size)
15651  iProcessor = (unsigned long)size-1;
15652  if (Global_Index >= nPoint_Linear[iProcessor])
15653  while(Global_Index >= nPoint_Linear[iProcessor+1]) iProcessor++;
15654  else
15655  while(Global_Index < nPoint_Linear[iProcessor]) iProcessor--;
15656 
15657  /*--- Load connectivity into the buffer for sending ---*/
15658 
15659  if (nElem_Flag[iProcessor] != ii) {
15660 
15661  nElem_Flag[iProcessor] = ii;
15662  unsigned long nn = index[iProcessor];
15663  unsigned long mm = haloIndex[iProcessor];
15664 
15665  /*--- Load the connectivity values. ---*/
15666 
15667  for (int kk = 0; kk < NODES_PER_ELEMENT; kk++) {
15668  iPoint = geometry->bound[iMarker][ii]->GetNode(kk);
15669  connSend[nn] = geometry->node[iPoint]->GetGlobalIndex(); nn++;
15670 
15671  /*--- Check if this is a halo node. If so, flag this element
15672  as a halo cell. We will use this later to sort and remove
15673  any duplicates from the connectivity list. ---*/
15674 
15675  if (Local_Halo[iPoint]) haloSend[mm] = true;
15676 
15677  }
15678 
15679  /*--- Increment the index by the message length ---*/
15680 
15681  index[iProcessor] += NODES_PER_ELEMENT;
15682  haloIndex[iProcessor]++;
15683 
15684  }
15685  }
15686  }
15687  }
15688  }
15689  }
15690 
15691  /*--- Free memory after loading up the send buffer. ---*/
15692 
15693  delete [] index;
15694  delete [] haloIndex;
15695 
15696  /*--- Allocate the memory that we need for receiving the conn
15697  values and then cue up the non-blocking receives. Note that
15698  we do not include our own rank in the communications. We will
15699  directly copy our own data later. ---*/
15700 
15701  unsigned long *connRecv = NULL;
15702  connRecv = new unsigned long[NODES_PER_ELEMENT*nElem_Recv[size]];
15703  for (int ii = 0; ii < NODES_PER_ELEMENT*nElem_Recv[size]; ii++)
15704  connRecv[ii] = 0;
15705 
15706  unsigned short *haloRecv = new unsigned short[nElem_Recv[size]];
15707  for (int ii = 0; ii < nElem_Recv[size]; ii++)
15708  haloRecv[ii] = false;
15709 
15710 #ifdef HAVE_MPI
15711  /*--- We need double the number of messages to send both the conn.
15712  and the flags for the halo cells. ---*/
15713 
15714  send_req = new SU2_MPI::Request[2*nSends];
15715  recv_req = new SU2_MPI::Request[2*nRecvs];
15716 
15717  /*--- Launch the non-blocking recv's for the connectivity. ---*/
15718 
15719  unsigned long iMessage = 0;
15720  for (int ii=0; ii<size; ii++) {
15721  if ((ii != rank) && (nElem_Recv[ii+1] > nElem_Recv[ii])) {
15722  int ll = NODES_PER_ELEMENT*nElem_Recv[ii];
15723  int kk = nElem_Recv[ii+1] - nElem_Recv[ii];
15724  int count = NODES_PER_ELEMENT*kk;
15725  int source = ii;
15726  int tag = ii + 1;
15727  SU2_MPI::Irecv(&(connRecv[ll]), count, MPI_UNSIGNED_LONG, source, tag,
15728  MPI_COMM_WORLD, &(recv_req[iMessage]));
15729  iMessage++;
15730  }
15731  }
15732 
15733  /*--- Launch the non-blocking sends of the connectivity. ---*/
15734 
15735  iMessage = 0;
15736  for (int ii=0; ii<size; ii++) {
15737  if ((ii != rank) && (nElem_Send[ii+1] > nElem_Send[ii])) {
15738  int ll = NODES_PER_ELEMENT*nElem_Send[ii];
15739  int kk = nElem_Send[ii+1] - nElem_Send[ii];
15740  int count = NODES_PER_ELEMENT*kk;
15741  int dest = ii;
15742  int tag = rank + 1;
15743  SU2_MPI::Isend(&(connSend[ll]), count, MPI_UNSIGNED_LONG, dest, tag,
15744  MPI_COMM_WORLD, &(send_req[iMessage]));
15745  iMessage++;
15746  }
15747  }
15748 
15749  /*--- Repeat the process to communicate the halo flags. ---*/
15750 
15751  iMessage = 0;
15752  for (int ii=0; ii<size; ii++) {
15753  if ((ii != rank) && (nElem_Recv[ii+1] > nElem_Recv[ii])) {
15754  int ll = nElem_Recv[ii];
15755  int kk = nElem_Recv[ii+1] - nElem_Recv[ii];
15756  int count = kk;
15757  int source = ii;
15758  int tag = ii + 1;
15759  SU2_MPI::Irecv(&(haloRecv[ll]), count, MPI_UNSIGNED_SHORT, source, tag,
15760  MPI_COMM_WORLD, &(recv_req[iMessage+nRecvs]));
15761  iMessage++;
15762  }
15763  }
15764 
15765  /*--- Launch the non-blocking sends of the halo flags. ---*/
15766 
15767  iMessage = 0;
15768  for (int ii=0; ii<size; ii++) {
15769  if ((ii != rank) && (nElem_Send[ii+1] > nElem_Send[ii])) {
15770  int ll = nElem_Send[ii];
15771  int kk = nElem_Send[ii+1] - nElem_Send[ii];
15772  int count = kk;
15773  int dest = ii;
15774  int tag = rank + 1;
15775  SU2_MPI::Isend(&(haloSend[ll]), count, MPI_UNSIGNED_SHORT, dest, tag,
15776  MPI_COMM_WORLD, &(send_req[iMessage+nSends]));
15777  iMessage++;
15778  }
15779  }
15780 #endif
15781 
15782  /*--- Copy my own rank's data into the recv buffer directly. ---*/
15783 
15784  int mm = NODES_PER_ELEMENT*nElem_Recv[rank];
15785  int ll = NODES_PER_ELEMENT*nElem_Send[rank];
15786  int kk = NODES_PER_ELEMENT*nElem_Send[rank+1];
15787 
15788  for (int nn=ll; nn<kk; nn++, mm++) connRecv[mm] = connSend[nn];
15789 
15790  mm = nElem_Recv[rank];
15791  ll = nElem_Send[rank];
15792  kk = nElem_Send[rank+1];
15793 
15794  for (int nn=ll; nn<kk; nn++, mm++) haloRecv[mm] = haloSend[nn];
15795 
15796  /*--- Wait for the non-blocking sends and recvs to complete. ---*/
15797 
15798 #ifdef HAVE_MPI
15799  int number = 2*nSends;
15800  for (int ii = 0; ii < number; ii++)
15801  SU2_MPI::Waitany(number, send_req, &ind, &status);
15802 
15803  number = 2*nRecvs;
15804  for (int ii = 0; ii < number; ii++)
15805  SU2_MPI::Waitany(number, recv_req, &ind, &status);
15806 
15807  delete [] send_req;
15808  delete [] recv_req;
15809 #endif
15810 
15811  /*--- Store the connectivity for this rank in the proper data
15812  structure before post-processing below. Note that we add 1 here
15813  to the connectivity for vizualization packages. First, allocate
15814  appropriate amount of memory for this section. ---*/
15815 
15816  if (nElem_Recv[size] > 0) Conn_Elem = new int[NODES_PER_ELEMENT*nElem_Recv[size]];
15817  int count = 0; nElem_Total = 0;
15818  for (int ii = 0; ii < nElem_Recv[size]; ii++) {
15819  if (!haloRecv[ii]) {
15820  nElem_Total++;
15821  for (int jj = 0; jj < NODES_PER_ELEMENT; jj++) {
15822  Conn_Elem[count] = (int)connRecv[ii*NODES_PER_ELEMENT+jj] + 1;
15823  count++;
15824  }
15825  }
15826  }
15827 
15828  /*--- Store the particular global element count in the class data,
15829  and set the class data pointer to the connectivity array. ---*/
15830 
15831  switch (Elem_Type) {
15832  case LINE:
15833  nParallel_Line = nElem_Total;
15834  Conn_BoundLine_Par = Conn_Elem;
15835  break;
15836  case TRIANGLE:
15837  nParallel_BoundTria = nElem_Total;
15838  Conn_BoundTria_Par = Conn_Elem;
15839  break;
15840  case QUADRILATERAL:
15841  nParallel_BoundQuad = nElem_Total;
15842  Conn_BoundQuad_Par = Conn_Elem;
15843  break;
15844  default:
15845  SU2_MPI::Error("Unrecognized element type", CURRENT_FUNCTION);
15846  break;
15847  }
15848 
15849  /*--- Free temporary memory from communications ---*/
15850 
15851  delete [] connSend;
15852  delete [] connRecv;
15853  delete [] haloSend;
15854  delete [] haloRecv;
15855  delete [] Local_Halo;
15856  delete [] nElem_Recv;
15857  delete [] nElem_Send;
15858  delete [] nElem_Flag;
15859  delete [] Buffer_Recv_nAddedPeriodic;
15860  delete [] Buffer_Send_AddedPeriodic;
15861  delete [] Buffer_Recv_AddedPeriodic;
15862  delete [] npoint_procs;
15863  delete [] starting_node;
15864  delete [] ending_node;
15865  delete [] nPoint_Linear;
15866 
15867 }
15868 
15870 
15871  unsigned short iMarker;
15872  unsigned long iProcessor;
15873  unsigned long iPoint, Global_Index, nLocalPoint, nTotalPoint, iVertex;
15874 
15875  int VARS_PER_POINT = nVar_Par;
15876  int *Local_Halo = NULL;
15877 
15878  bool isPeriodic;
15879 
15880 #ifdef HAVE_MPI
15881  SU2_MPI::Request *send_req, *recv_req;
15882  SU2_MPI::Status status;
15883  int ind;
15884 #endif
15885 
15886  /*--- Search all send/recv boundaries on this partition for any periodic
15887  nodes that were part of the original domain. We want to recover these
15888  for visualization purposes. ---*/
15889 
15890  Local_Halo = new int[geometry->GetnPoint()];
15891  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
15892  Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain();
15893 
15894  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
15895  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
15896 
15897  /*--- Checking for less than or equal to the rank, because there may
15898  be some periodic halo nodes that send info to the same rank. ---*/
15899 
15900  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
15901  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
15902  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
15903  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1));
15904  if (isPeriodic) Local_Halo[iPoint] = false;
15905  }
15906  }
15907  }
15908 
15909  /*--- Sum total number of nodes that belong to the domain ---*/
15910 
15911  nLocalPoint = 0;
15912  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
15913  if (Local_Halo[iPoint] == false)
15914  nLocalPoint++;
15915 
15916 #ifdef HAVE_MPI
15917  SU2_MPI::Allreduce(&nLocalPoint, &nTotalPoint, 1,
15919 #else
15920  nTotalPoint = nLocalPoint;
15921 #endif
15922 
15923  /*--- Now that we know the actual number of points we need to output,
15924  compute the number of points that will be on each processor.
15925  This is a linear partitioning with the addition of a simple load
15926  balancing for any remainder points. ---*/
15927 
15928  unsigned long *npoint_procs = new unsigned long[size];
15929  unsigned long *starting_node = new unsigned long[size];
15930  unsigned long *ending_node = new unsigned long[size];
15931  unsigned long *nPoint_Linear = new unsigned long[size+1];
15932 
15933  unsigned long total_pt_accounted = 0;
15934  for (int ii = 0; ii < size; ii++) {
15935  npoint_procs[ii] = nTotalPoint/size;
15936  total_pt_accounted = total_pt_accounted + npoint_procs[ii];
15937  }
15938 
15939  /*--- Get the number of remainder points after the even division. ---*/
15940 
15941  unsigned long rem_points = nTotalPoint-total_pt_accounted;
15942  for (unsigned long ii = 0; ii < rem_points; ii++) {
15943  npoint_procs[ii]++;
15944  }
15945 
15946  /*--- Store the local number of nodes and the beginning/end index ---*/
15947 
15948  starting_node[0] = 0;
15949  ending_node[0] = starting_node[0] + npoint_procs[0];
15950  nPoint_Linear[0] = 0;
15951  for (int ii = 1; ii < size; ii++) {
15952  starting_node[ii] = ending_node[ii-1];
15953  ending_node[ii] = starting_node[ii] + npoint_procs[ii];
15954  nPoint_Linear[ii] = nPoint_Linear[ii-1] + npoint_procs[ii-1];
15955  }
15956  nPoint_Linear[size] = nTotalPoint;
15957 
15958  /*--- We start with the grid nodes distributed across all procs with
15959  no particular ordering assumed. We need to loop through our local partition
15960  and decide how many nodes we must send to each other rank in order to
15961  have all nodes sorted according to a linear partitioning of the grid
15962  nodes, i.e., rank 0 holds the first ~ nGlobalPoint()/nProcessors nodes.
15963  First, initialize a counter and flag. ---*/
15964 
15965  int *nPoint_Send = new int[size+1]; nPoint_Send[0] = 0;
15966  int *nPoint_Recv = new int[size+1]; nPoint_Recv[0] = 0;
15967  int *nPoint_Flag = new int[size];
15968 
15969  for (int ii=0; ii < size; ii++) {
15970  nPoint_Send[ii] = 0;
15971  nPoint_Recv[ii] = 0;
15972  nPoint_Flag[ii]= -1;
15973  }
15974  nPoint_Send[size] = 0; nPoint_Recv[size] = 0;
15975 
15976  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++ ) {
15977 
15978  /*--- We only write interior points and recovered periodic points. ---*/
15979 
15980  if (!Local_Halo[iPoint]) {
15981 
15982  /*--- Get the global index of the current point. ---*/
15983 
15984  Global_Index = geometry->node[iPoint]->GetGlobalIndex();
15985 
15986  /*--- Search for the processor that owns this point ---*/
15987 
15988  iProcessor = Global_Index/npoint_procs[0];
15989  if (iProcessor >= (unsigned long)size)
15990  iProcessor = (unsigned long)size-1;
15991  if (Global_Index >= nPoint_Linear[iProcessor])
15992  while(Global_Index >= nPoint_Linear[iProcessor+1]) iProcessor++;
15993  else
15994  while(Global_Index < nPoint_Linear[iProcessor]) iProcessor--;
15995 
15996  /*--- If we have not visited this node yet, increment our
15997  number of elements that must be sent to a particular proc. ---*/
15998 
15999  if (nPoint_Flag[iProcessor] != (int)iPoint) {
16000  nPoint_Flag[iProcessor] = (int)iPoint;
16001  nPoint_Send[iProcessor+1]++;
16002  }
16003 
16004  }
16005  }
16006 
16007  /*--- Communicate the number of nodes to be sent/recv'd amongst
16008  all processors. After this communication, each proc knows how
16009  many cells it will receive from each other processor. ---*/
16010 
16011 #ifdef HAVE_MPI
16012  SU2_MPI::Alltoall(&(nPoint_Send[1]), 1, MPI_INT,
16013  &(nPoint_Recv[1]), 1, MPI_INT, MPI_COMM_WORLD);
16014 #else
16015  nPoint_Recv[1] = nPoint_Send[1];
16016 #endif
16017 
16018  /*--- Prepare to send coordinates. First check how many
16019  messages we will be sending and receiving. Here we also put
16020  the counters into cumulative storage format to make the
16021  communications simpler. ---*/
16022 
16023  int nSends = 0, nRecvs = 0;
16024  for (int ii=0; ii < size; ii++) nPoint_Flag[ii] = -1;
16025 
16026  for (int ii = 0; ii < size; ii++) {
16027  if ((ii != rank) && (nPoint_Send[ii+1] > 0)) nSends++;
16028  if ((ii != rank) && (nPoint_Recv[ii+1] > 0)) nRecvs++;
16029 
16030  nPoint_Send[ii+1] += nPoint_Send[ii];
16031  nPoint_Recv[ii+1] += nPoint_Recv[ii];
16032  }
16033 
16034  /*--- Allocate memory to hold the connectivity that we are
16035  sending. ---*/
16036 
16037  su2double *connSend = NULL;
16038  connSend = new su2double[VARS_PER_POINT*nPoint_Send[size]];
16039  for (int ii = 0; ii < VARS_PER_POINT*nPoint_Send[size]; ii++)
16040  connSend[ii] = 0;
16041 
16042  /*--- Allocate arrays for sending the global ID. ---*/
16043 
16044  unsigned long *idSend = new unsigned long[nPoint_Send[size]];
16045  for (int ii = 0; ii < nPoint_Send[size]; ii++)
16046  idSend[ii] = 0;
16047 
16048  /*--- Create an index variable to keep track of our index
16049  positions as we load up the send buffer. ---*/
16050 
16051  unsigned long *index = new unsigned long[size];
16052  for (int ii=0; ii < size; ii++) index[ii] = VARS_PER_POINT*nPoint_Send[ii];
16053 
16054  unsigned long *idIndex = new unsigned long[size];
16055  for (int ii=0; ii < size; ii++) idIndex[ii] = nPoint_Send[ii];
16056 
16057  /*--- Loop through our elements and load the elems and their
16058  additional data that we will send to the other procs. ---*/
16059 
16060  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
16061 
16062  /*--- We only write interior points and recovered periodic points. ---*/
16063 
16064  if (!Local_Halo[iPoint]) {
16065 
16066  /*--- Get the index of the current point. ---*/
16067 
16068  Global_Index = geometry->node[iPoint]->GetGlobalIndex();
16069 
16070  /*--- Search for the processor that owns this point. ---*/
16071 
16072  iProcessor = Global_Index/npoint_procs[0];
16073  if (iProcessor >= (unsigned long)size)
16074  iProcessor = (unsigned long)size-1;
16075  if (Global_Index >= nPoint_Linear[iProcessor])
16076  while(Global_Index >= nPoint_Linear[iProcessor+1]) iProcessor++;
16077  else
16078  while(Global_Index < nPoint_Linear[iProcessor]) iProcessor--;
16079 
16080  /*--- Load node coordinates into the buffer for sending. ---*/
16081 
16082  if (nPoint_Flag[iProcessor] != (int)iPoint) {
16083 
16084  nPoint_Flag[iProcessor] = (int)iPoint;
16085  unsigned long nn = index[iProcessor];
16086 
16087  /*--- Load the data values. ---*/
16088 
16089  for (unsigned short kk = 0; kk < VARS_PER_POINT; kk++) {
16090  connSend[nn] = Local_Data[iPoint][kk]; nn++;
16091  }
16092 
16093  /*--- Load the global ID (minus offset) for sorting the
16094  points once they all reach the correct processor. ---*/
16095 
16096  nn = idIndex[iProcessor];
16097  idSend[nn] = Global_Index - starting_node[iProcessor];
16098 
16099  /*--- Increment the index by the message length ---*/
16100 
16101  index[iProcessor] += VARS_PER_POINT;
16102  idIndex[iProcessor]++;
16103 
16104  }
16105  }
16106  }
16107 
16108  /*--- Free memory after loading up the send buffer. ---*/
16109 
16110  delete [] index;
16111  delete [] idIndex;
16112 
16113  /*--- Allocate the memory that we need for receiving the conn
16114  values and then cue up the non-blocking receives. Note that
16115  we do not include our own rank in the communications. We will
16116  directly copy our own data later. ---*/
16117 
16118  su2double *connRecv = NULL;
16119  connRecv = new su2double[VARS_PER_POINT*nPoint_Recv[size]];
16120  for (int ii = 0; ii < VARS_PER_POINT*nPoint_Recv[size]; ii++)
16121  connRecv[ii] = 0;
16122 
16123  unsigned long *idRecv = new unsigned long[nPoint_Recv[size]];
16124  for (int ii = 0; ii < nPoint_Recv[size]; ii++)
16125  idRecv[ii] = 0;
16126 
16127 #ifdef HAVE_MPI
16128  /*--- We need double the number of messages to send both the conn.
16129  and the global IDs. ---*/
16130 
16131  send_req = new SU2_MPI::Request[2*nSends];
16132  recv_req = new SU2_MPI::Request[2*nRecvs];
16133 
16134  unsigned long iMessage = 0;
16135  for (int ii=0; ii<size; ii++) {
16136  if ((ii != rank) && (nPoint_Recv[ii+1] > nPoint_Recv[ii])) {
16137  int ll = VARS_PER_POINT*nPoint_Recv[ii];
16138  int kk = nPoint_Recv[ii+1] - nPoint_Recv[ii];
16139  int count = VARS_PER_POINT*kk;
16140  int source = ii;
16141  int tag = ii + 1;
16142  SU2_MPI::Irecv(&(connRecv[ll]), count, MPI_DOUBLE, source, tag,
16143  MPI_COMM_WORLD, &(recv_req[iMessage]));
16144  iMessage++;
16145  }
16146  }
16147 
16148  /*--- Launch the non-blocking sends of the connectivity. ---*/
16149 
16150  iMessage = 0;
16151  for (int ii=0; ii<size; ii++) {
16152  if ((ii != rank) && (nPoint_Send[ii+1] > nPoint_Send[ii])) {
16153  int ll = VARS_PER_POINT*nPoint_Send[ii];
16154  int kk = nPoint_Send[ii+1] - nPoint_Send[ii];
16155  int count = VARS_PER_POINT*kk;
16156  int dest = ii;
16157  int tag = rank + 1;
16158  SU2_MPI::Isend(&(connSend[ll]), count, MPI_DOUBLE, dest, tag,
16159  MPI_COMM_WORLD, &(send_req[iMessage]));
16160  iMessage++;
16161  }
16162  }
16163 
16164  /*--- Repeat the process to communicate the global IDs. ---*/
16165 
16166  iMessage = 0;
16167  for (int ii=0; ii<size; ii++) {
16168  if ((ii != rank) && (nPoint_Recv[ii+1] > nPoint_Recv[ii])) {
16169  int ll = nPoint_Recv[ii];
16170  int kk = nPoint_Recv[ii+1] - nPoint_Recv[ii];
16171  int count = kk;
16172  int source = ii;
16173  int tag = ii + 1;
16174  SU2_MPI::Irecv(&(idRecv[ll]), count, MPI_UNSIGNED_LONG, source, tag,
16175  MPI_COMM_WORLD, &(recv_req[iMessage+nRecvs]));
16176  iMessage++;
16177  }
16178  }
16179 
16180  /*--- Launch the non-blocking sends of the global IDs. ---*/
16181 
16182  iMessage = 0;
16183  for (int ii=0; ii<size; ii++) {
16184  if ((ii != rank) && (nPoint_Send[ii+1] > nPoint_Send[ii])) {
16185  int ll = nPoint_Send[ii];
16186  int kk = nPoint_Send[ii+1] - nPoint_Send[ii];
16187  int count = kk;
16188  int dest = ii;
16189  int tag = rank + 1;
16190  SU2_MPI::Isend(&(idSend[ll]), count, MPI_UNSIGNED_LONG, dest, tag,
16191  MPI_COMM_WORLD, &(send_req[iMessage+nSends]));
16192  iMessage++;
16193  }
16194  }
16195 #endif
16196 
16197  /*--- Copy my own rank's data into the recv buffer directly. ---*/
16198 
16199  int mm = VARS_PER_POINT*nPoint_Recv[rank];
16200  int ll = VARS_PER_POINT*nPoint_Send[rank];
16201  int kk = VARS_PER_POINT*nPoint_Send[rank+1];
16202 
16203  for (int nn=ll; nn<kk; nn++, mm++) connRecv[mm] = connSend[nn];
16204 
16205  mm = nPoint_Recv[rank];
16206  ll = nPoint_Send[rank];
16207  kk = nPoint_Send[rank+1];
16208 
16209  for (int nn=ll; nn<kk; nn++, mm++) idRecv[mm] = idSend[nn];
16210 
16211  /*--- Wait for the non-blocking sends and recvs to complete. ---*/
16212 
16213 #ifdef HAVE_MPI
16214  int number = 2*nSends;
16215  for (int ii = 0; ii < number; ii++)
16216  SU2_MPI::Waitany(number, send_req, &ind, &status);
16217 
16218  number = 2*nRecvs;
16219  for (int ii = 0; ii < number; ii++)
16220  SU2_MPI::Waitany(number, recv_req, &ind, &status);
16221 
16222  delete [] send_req;
16223  delete [] recv_req;
16224 #endif
16225 
16226  /*--- Store the connectivity for this rank in the proper data
16227  structure before post-processing below. First, allocate the
16228  appropriate amount of memory for this section. ---*/
16229 
16230  Parallel_Data = new su2double*[VARS_PER_POINT];
16231  for (int jj = 0; jj < VARS_PER_POINT; jj++) {
16232  Parallel_Data[jj] = new su2double[nPoint_Recv[size]];
16233  for (int ii = 0; ii < nPoint_Recv[size]; ii++) {
16234  Parallel_Data[jj][idRecv[ii]] = connRecv[ii*VARS_PER_POINT+jj];
16235  }
16236  }
16237 
16238  /*--- Store the total number of local points my rank has for
16239  the current section after completing the communications. ---*/
16240 
16241  nParallel_Poin = nPoint_Recv[size];
16242 
16243  /*--- Reduce the total number of points we will write in the output files. ---*/
16244 
16245 #ifndef HAVE_MPI
16246  nGlobal_Poin_Par = nParallel_Poin;
16247 #else
16248  SU2_MPI::Allreduce(&nParallel_Poin, &nGlobal_Poin_Par, 1,
16250 #endif
16251 
16252  /*--- Free temporary memory from communications ---*/
16253 
16254  delete [] connSend;
16255  delete [] connRecv;
16256  delete [] idSend;
16257  delete [] idRecv;
16258  delete [] nPoint_Recv;
16259  delete [] nPoint_Send;
16260  delete [] nPoint_Flag;
16261 
16262  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
16263  delete [] Local_Data[iPoint];
16264  delete [] Local_Data;
16265 
16266  delete [] Local_Halo;
16267  delete [] npoint_procs;
16268  delete [] starting_node;
16269  delete [] ending_node;
16270  delete [] nPoint_Linear;
16271 
16272 }
16273 
16275 
16276  unsigned short iMarker;
16277  unsigned long iProcessor;
16278  unsigned long iPoint, jPoint, kPoint, iElem;
16279  unsigned long Global_Index, nLocalPoint, nTotalPoint, iVertex;
16280 
16281  int VARS_PER_POINT = nVar_Par;
16282  int *Local_Halo = NULL;
16283  int iNode, count;
16284  int SendRecv, RecvFrom;
16285 
16286  bool notPeriodic, notHalo, addedPeriodic, isPeriodic;
16287 
16288 #ifdef HAVE_MPI
16289  SU2_MPI::Request *send_req, *recv_req;
16290  SU2_MPI::Status status;
16291  int ind;
16292 #endif
16293 
16294  /*--------------------------------------------------------------------------*/
16295  /*--- Step 1: We already have the surface connectivity spread out in ---*/
16296  /*--- linear partitions across all procs and the output data ---*/
16297  /*--- for the entire field is similarly linearly partitioned. ---*/
16298  /*--- We need to identify which nodes in the volume data are ---*/
16299  /*--- also surface points. Our first step is to loop over all ---*/
16300  /*--- of the sorted surface connectivity and create a data ---*/
16301  /*--- structure on each proc that can identify the local surf ---*/
16302  /*--- points. Note that the linear partitioning is slightly ---*/
16303  /*--- different between the nodes and elements, so we will ---*/
16304  /*--- have to move between the two systems in this routine. ---*/
16305  /*--------------------------------------------------------------------------*/
16306 
16307  /*--- Search all send/recv boundaries on this partition for any periodic
16308  nodes that were part of the original domain. We want to recover these
16309  for visualization purposes. This is the linear partitioning for nodes. ---*/
16310 
16311  Local_Halo = new int[geometry->GetnPoint()];
16312  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
16313  Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain();
16314 
16315  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
16316  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
16317 
16318  /*--- Checking for less than or equal to the rank, because there may
16319  be some periodic halo nodes that send info to the same rank. ---*/
16320 
16321  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
16322  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
16323  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
16324  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1));
16325  if (isPeriodic) Local_Halo[iPoint] = false;
16326  }
16327  }
16328  }
16329 
16330  /*--- Sum total number of nodes that belong to the domain ---*/
16331 
16332  nLocalPoint = 0;
16333  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
16334  if (Local_Halo[iPoint] == false)
16335  nLocalPoint++;
16336 
16337 #ifdef HAVE_MPI
16338  SU2_MPI::Allreduce(&nLocalPoint, &nTotalPoint, 1,
16340 #else
16341  nTotalPoint = nLocalPoint;
16342 #endif
16343 
16344  /*--- Now that we know the actual number of points we need to output,
16345  compute the number of points that will be on each processor.
16346  This is a linear partitioning with the addition of a simple load
16347  balancing for any remainder points. ---*/
16348 
16349  unsigned long *npoint_procs = new unsigned long[size];
16350  unsigned long *starting_node = new unsigned long[size];
16351  unsigned long *ending_node = new unsigned long[size];
16352 
16353  unsigned long *nPoint_Linear_Nodes = new unsigned long[size+1];
16354  unsigned long *nPoint_Linear_Elems = new unsigned long[size+1];
16355 
16356  unsigned long total_pt_accounted = 0;
16357  for (int ii = 0; ii < size; ii++) {
16358  npoint_procs[ii] = nTotalPoint/size;
16359  total_pt_accounted = total_pt_accounted + npoint_procs[ii];
16360  }
16361 
16362  /*--- Get the number of remainder points after the even division. ---*/
16363 
16364  unsigned long rem_points = nTotalPoint-total_pt_accounted;
16365  for (unsigned long ii = 0; ii < rem_points; ii++) {
16366  npoint_procs[ii]++;
16367  }
16368 
16369  /*--- Store the local number of nodes and the beginning/end index ---*/
16370 
16371  starting_node[0] = 0;
16372  ending_node[0] = starting_node[0] + npoint_procs[0];
16373  nPoint_Linear_Nodes[0] = 0;
16374  for (int ii = 1; ii < size; ii++) {
16375  starting_node[ii] = ending_node[ii-1];
16376  ending_node[ii] = starting_node[ii] + npoint_procs[ii];
16377  nPoint_Linear_Nodes[ii] = nPoint_Linear_Nodes[ii-1] + npoint_procs[ii-1];
16378  }
16379  nPoint_Linear_Nodes[size] = nTotalPoint;
16380 
16381  /*--- Prepare to check and communicate the nodes that each proc has
16382  locally from the surface connectivity. ---*/
16383 
16384  int *nElem_Send = new int[size+1]; nElem_Send[0] = 0;
16385  int *nElem_Recv = new int[size+1]; nElem_Recv[0] = 0;
16386  int *nElem_Flag = new int[size];
16387 
16388  for (int ii=0; ii < size; ii++) {
16389  nElem_Send[ii] = 0;
16390  nElem_Recv[ii] = 0;
16391  nElem_Flag[ii]= -1;
16392  }
16393  nElem_Send[size] = 0; nElem_Recv[size] = 0;
16394 
16395  /*--- Loop through our local line elements and check where each
16396  of the grid nodes resides based on global index. ---*/
16397 
16398  for (int ii = 0; ii < (int)nParallel_Line; ii++) {
16399  for ( int jj = 0; jj < N_POINTS_LINE; jj++ ) {
16400 
16401  /*--- Get global index. Note the -1 since it was 1-based for viz. ---*/
16402 
16403  iNode = ii*N_POINTS_LINE+jj;
16404  Global_Index = Conn_BoundLine_Par[iNode]-1;
16405 
16406  /*--- Search for the processor that owns this point ---*/
16407 
16408  iProcessor = Global_Index/npoint_procs[0];
16409  if (iProcessor >= (unsigned long)size)
16410  iProcessor = (unsigned long)size-1;
16411  if (Global_Index >= nPoint_Linear_Nodes[iProcessor])
16412  while(Global_Index >= nPoint_Linear_Nodes[iProcessor+1]) iProcessor++;
16413  else
16414  while(Global_Index < nPoint_Linear_Nodes[iProcessor]) iProcessor--;
16415 
16416  /*--- If we have not visited this element yet, increment our
16417  number of elements that must be sent to a particular proc. ---*/
16418 
16419  if ((nElem_Flag[iProcessor] != iNode)) {
16420  nElem_Flag[iProcessor] = iNode;
16421  nElem_Send[iProcessor+1]++;
16422  }
16423 
16424  }
16425  }
16426 
16427  /*--- Reset out flags and then loop through our local triangle surface
16428  elements performing the same check for where each grid node resides. ---*/
16429 
16430  for (int ii=0; ii < size; ii++) nElem_Flag[ii]= -1;
16431 
16432  for (int ii = 0; ii < (int)nParallel_BoundTria; ii++) {
16433  for ( int jj = 0; jj < N_POINTS_TRIANGLE; jj++ ) {
16434 
16435  /*--- Get global index. Note the -1 since it was 1-based for viz. ---*/
16436 
16437  iNode = ii*N_POINTS_TRIANGLE + jj;
16438  Global_Index = Conn_BoundTria_Par[iNode]-1;
16439 
16440  /*--- Search for the processor that owns this point ---*/
16441 
16442  iProcessor = Global_Index/npoint_procs[0];
16443  if (iProcessor >= (unsigned long)size)
16444  iProcessor = (unsigned long)size-1;
16445  if (Global_Index >= nPoint_Linear_Nodes[iProcessor])
16446  while(Global_Index >= nPoint_Linear_Nodes[iProcessor+1]) iProcessor++;
16447  else
16448  while(Global_Index < nPoint_Linear_Nodes[iProcessor]) iProcessor--;
16449 
16450  /*--- If we have not visited this element yet, increment our
16451  number of elements that must be sent to a particular proc. ---*/
16452 
16453  if ((nElem_Flag[iProcessor] != iNode)) {
16454  nElem_Flag[iProcessor] = iNode;
16455  nElem_Send[iProcessor+1]++;
16456  }
16457 
16458  }
16459  }
16460 
16461  /*--- Reset out flags and then loop through our local quad surface
16462  elements performing the same check for where each grid node resides. ---*/
16463 
16464  for (int ii=0; ii < size; ii++) nElem_Flag[ii]= -1;
16465 
16466  for (int ii = 0; ii < (int)nParallel_BoundQuad; ii++) {
16467  for ( int jj = 0; jj < N_POINTS_QUADRILATERAL; jj++ ) {
16468 
16469  /*--- Get global index. Note the -1 since it was 1-based for viz. ---*/
16470 
16471  iNode = ii*N_POINTS_QUADRILATERAL+jj;
16472  Global_Index = Conn_BoundQuad_Par[iNode]-1;
16473 
16474  /*--- Search for the processor that owns this point ---*/
16475 
16476  iProcessor = Global_Index/npoint_procs[0];
16477  if (iProcessor >= (unsigned long)size)
16478  iProcessor = (unsigned long)size-1;
16479  if (Global_Index >= nPoint_Linear_Nodes[iProcessor])
16480  while(Global_Index >= nPoint_Linear_Nodes[iProcessor+1]) iProcessor++;
16481  else
16482  while(Global_Index < nPoint_Linear_Nodes[iProcessor]) iProcessor--;
16483 
16484  /*--- If we have not visited this element yet, increment our
16485  number of elements that must be sent to a particular proc. ---*/
16486 
16487  if ((nElem_Flag[iProcessor] != iNode)) {
16488  nElem_Flag[iProcessor] = iNode;
16489  nElem_Send[iProcessor+1]++;
16490  }
16491 
16492  }
16493  }
16494 
16495  /*--- Communicate the number of nodes to be sent/recv'd amongst
16496  all processors. After this communication, each proc knows how
16497  many nodes it will receive from each other processor. ---*/
16498 
16499 #ifdef HAVE_MPI
16500  SU2_MPI::Alltoall(&(nElem_Send[1]), 1, MPI_INT,
16501  &(nElem_Recv[1]), 1, MPI_INT, MPI_COMM_WORLD);
16502 #else
16503  nElem_Recv[1] = nElem_Send[1];
16504 #endif
16505 
16506  /*--- Prepare to send. First check how many
16507  messages we will be sending and receiving. Here we also put
16508  the counters into cumulative storage format to make the
16509  communications simpler. ---*/
16510 
16511  int nSends = 0, nRecvs = 0;
16512  for (int ii=0; ii < size; ii++) nElem_Flag[ii] = -1;
16513 
16514  for (int ii = 0; ii < size; ii++) {
16515  if ((ii != rank) && (nElem_Send[ii+1] > 0)) nSends++;
16516  if ((ii != rank) && (nElem_Recv[ii+1] > 0)) nRecvs++;
16517 
16518  nElem_Send[ii+1] += nElem_Send[ii];
16519  nElem_Recv[ii+1] += nElem_Recv[ii];
16520  }
16521 
16522  /*--- Allocate arrays for sending the global ID. ---*/
16523 
16524  unsigned long *idSend = new unsigned long[nElem_Send[size]];
16525  for (int ii = 0; ii < nElem_Send[size]; ii++) idSend[ii] = 0;
16526 
16527  /*--- Create an index variable to keep track of our index
16528  positions as we load up the send buffer. ---*/
16529 
16530  unsigned long *idIndex = new unsigned long[size];
16531  for (int ii=0; ii < size; ii++) idIndex[ii] = nElem_Send[ii];
16532 
16533  /*--- Now loop back through the local connectivities for the surface
16534  elements and load up the global IDs for sending to their home proc. ---*/
16535 
16536  for (int ii = 0; ii < (int)nParallel_Line; ii++) {
16537  for ( int jj = 0; jj < N_POINTS_LINE; jj++ ) {
16538 
16539  /*--- Get global index. Note the -1 since it was 1-based for viz. ---*/
16540 
16541  iNode = ii*N_POINTS_LINE+jj;
16542  Global_Index = Conn_BoundLine_Par[iNode]-1;
16543 
16544  /*--- Search for the processor that owns this point ---*/
16545 
16546  iProcessor = Global_Index/npoint_procs[0];
16547  if (iProcessor >= (unsigned long)size)
16548  iProcessor = (unsigned long)size-1;
16549  if (Global_Index >= nPoint_Linear_Nodes[iProcessor])
16550  while(Global_Index >= nPoint_Linear_Nodes[iProcessor+1]) iProcessor++;
16551  else
16552  while(Global_Index < nPoint_Linear_Nodes[iProcessor]) iProcessor--;
16553 
16554  /*--- Load global ID into the buffer for sending ---*/
16555 
16556  if (nElem_Flag[iProcessor] != iNode) {
16557 
16558  nElem_Flag[iProcessor] = iNode;
16559  unsigned long nn = idIndex[iProcessor];
16560 
16561  /*--- Load the connectivity values. ---*/
16562 
16563  idSend[nn] = Global_Index; nn++;
16564 
16565  /*--- Increment the index by the message length ---*/
16566 
16567  idIndex[iProcessor]++;
16568 
16569  }
16570 
16571  }
16572  }
16573 
16574  for (int ii=0; ii < size; ii++) nElem_Flag[ii]= -1;
16575 
16576  for (int ii = 0; ii < (int)nParallel_BoundTria; ii++) {
16577  for ( int jj = 0; jj < N_POINTS_TRIANGLE; jj++ ) {
16578 
16579  /*--- Get global index. Note the -1 since it was 1-based for viz. ---*/
16580 
16581  iNode = ii*N_POINTS_TRIANGLE + jj;
16582  Global_Index = Conn_BoundTria_Par[iNode]-1;
16583 
16584  /*--- Search for the processor that owns this point ---*/
16585 
16586  iProcessor = Global_Index/npoint_procs[0];
16587  if (iProcessor >= (unsigned long)size)
16588  iProcessor = (unsigned long)size-1;
16589  if (Global_Index >= nPoint_Linear_Nodes[iProcessor])
16590  while(Global_Index >= nPoint_Linear_Nodes[iProcessor+1]) iProcessor++;
16591  else
16592  while(Global_Index < nPoint_Linear_Nodes[iProcessor]) iProcessor--;
16593 
16594  /*--- Load global ID into the buffer for sending ---*/
16595 
16596  if (nElem_Flag[iProcessor] != iNode) {
16597 
16598  nElem_Flag[iProcessor] = iNode;
16599  unsigned long nn = idIndex[iProcessor];
16600 
16601  /*--- Load the connectivity values. ---*/
16602 
16603  idSend[nn] = Global_Index; nn++;
16604 
16605  /*--- Increment the index by the message length ---*/
16606 
16607  idIndex[iProcessor]++;
16608 
16609  }
16610 
16611  }
16612  }
16613 
16614  for (int ii=0; ii < size; ii++) nElem_Flag[ii]= -1;
16615 
16616  for (int ii = 0; ii < (int)nParallel_BoundQuad; ii++) {
16617  for ( int jj = 0; jj < N_POINTS_QUADRILATERAL; jj++ ) {
16618 
16619  /*--- Get global index. Note the -1 since it was 1-based for viz. ---*/
16620 
16621  iNode = ii*N_POINTS_QUADRILATERAL+jj;
16622  Global_Index = Conn_BoundQuad_Par[iNode]-1;
16623 
16624  /*--- Search for the processor that owns this point ---*/
16625 
16626  iProcessor = Global_Index/npoint_procs[0];
16627  if (iProcessor >= (unsigned long)size)
16628  iProcessor = (unsigned long)size-1;
16629  if (Global_Index >= nPoint_Linear_Nodes[iProcessor])
16630  while(Global_Index >= nPoint_Linear_Nodes[iProcessor+1]) iProcessor++;
16631  else
16632  while(Global_Index < nPoint_Linear_Nodes[iProcessor]) iProcessor--;
16633 
16634  /*--- Load global ID into the buffer for sending ---*/
16635 
16636  if (nElem_Flag[iProcessor] != iNode) {
16637 
16638  nElem_Flag[iProcessor] = iNode;
16639  unsigned long nn = idIndex[iProcessor];
16640 
16641  /*--- Load the connectivity values. ---*/
16642 
16643  idSend[nn] = Global_Index; nn++;
16644 
16645  /*--- Increment the index by the message length ---*/
16646 
16647  idIndex[iProcessor]++;
16648 
16649  }
16650 
16651  }
16652  }
16653 
16654  /*--- Allocate the memory that we need for receiving the global IDs
16655  values and then cue up the non-blocking receives. Note that
16656  we do not include our own rank in the communications. We will
16657  directly copy our own data later. ---*/
16658 
16659  unsigned long *idRecv = NULL;
16660  idRecv = new unsigned long[nElem_Recv[size]];
16661  for (int ii = 0; ii < nElem_Recv[size]; ii++)
16662  idRecv[ii] = 0;
16663 
16664 #ifdef HAVE_MPI
16665  /*--- We need double the number of messages to send both the conn.
16666  and the flags for the halo cells. ---*/
16667 
16668  send_req = new SU2_MPI::Request[nSends];
16669  recv_req = new SU2_MPI::Request[nRecvs];
16670 
16671  /*--- Launch the non-blocking recv's for the global IDs. ---*/
16672 
16673  unsigned long iMessage = 0;
16674  for (int ii=0; ii<size; ii++) {
16675  if ((ii != rank) && (nElem_Recv[ii+1] > nElem_Recv[ii])) {
16676  int ll = nElem_Recv[ii];
16677  int kk = nElem_Recv[ii+1] - nElem_Recv[ii];
16678  int count = kk;
16679  int source = ii;
16680  int tag = ii + 1;
16681  SU2_MPI::Irecv(&(idRecv[ll]), count, MPI_UNSIGNED_LONG, source, tag,
16682  MPI_COMM_WORLD, &(recv_req[iMessage]));
16683  iMessage++;
16684  }
16685  }
16686 
16687  /*--- Launch the non-blocking sends of the global IDs. ---*/
16688 
16689  iMessage = 0;
16690  for (int ii=0; ii<size; ii++) {
16691  if ((ii != rank) && (nElem_Send[ii+1] > nElem_Send[ii])) {
16692  int ll = nElem_Send[ii];
16693  int kk = nElem_Send[ii+1] - nElem_Send[ii];
16694  int count = kk;
16695  int dest = ii;
16696  int tag = rank + 1;
16697  SU2_MPI::Isend(&(idSend[ll]), count, MPI_UNSIGNED_LONG, dest, tag,
16698  MPI_COMM_WORLD, &(send_req[iMessage]));
16699  iMessage++;
16700  }
16701  }
16702 #endif
16703 
16704  /*--- Copy my own rank's data into the recv buffer directly. ---*/
16705 
16706  int mm = nElem_Recv[rank];
16707  int ll = nElem_Send[rank];
16708  int kk = nElem_Send[rank+1];
16709 
16710  for (int nn=ll; nn<kk; nn++, mm++) idRecv[mm] = idSend[nn];
16711 
16712  /*--- Wait for the non-blocking sends and recvs to complete. ---*/
16713 
16714 #ifdef HAVE_MPI
16715  int number = nSends;
16716  for (int ii = 0; ii < number; ii++)
16717  SU2_MPI::Waitany(number, send_req, &ind, &status);
16718 
16719  number = nRecvs;
16720  for (int ii = 0; ii < number; ii++)
16721  SU2_MPI::Waitany(number, recv_req, &ind, &status);
16722 
16723  delete [] send_req;
16724  delete [] recv_req;
16725 #endif
16726 
16727  /*--------------------------------------------------------------------------*/
16728  /*--- Step 2: Each proc now knows which is its local grid nodes from ---*/
16729  /*--- the entire volume solution are part of the surface. We ---*/
16730  /*--- now apply a mask to extract just those points on the ---*/
16731  /*--- surface. We also need to perform a renumbering so that ---*/
16732  /*--- the surface data (nodes and connectivity) have their ---*/
16733  /*--- own global numbering. This is important for writing ---*/
16734  /*--- output files in a later routine. ---*/
16735  /*--------------------------------------------------------------------------*/
16736 
16737  /*--- Create a local data structure that acts as a mask to extract the
16738  set of points within the local set that are on the surface. ---*/
16739 
16740  int *surfPoint = new int[nParallel_Poin];
16741  for (iPoint = 0; iPoint < nParallel_Poin; iPoint++) surfPoint[iPoint] = -1;
16742 
16743  for (int ii = 0; ii < nElem_Recv[size]; ii++) {
16744  surfPoint[(int)idRecv[ii]- starting_node[rank]] = (int)idRecv[ii];
16745  }
16746 
16747  /*--- First, add up the number of surface points I have on my rank. ---*/
16748 
16749  nSurf_Poin_Par = 0;
16750  for (iPoint = 0; iPoint < nParallel_Poin; iPoint++) {
16751  if (surfPoint[iPoint] != -1) {
16752  nSurf_Poin_Par++;
16753  }
16754  }
16755 
16756  /*--- Communicate this number of local surface points to all other
16757  processors so that it can be used to create offsets for the new
16758  global numbering for the surface points. ---*/
16759 
16760  int *nPoint_Send = new int[size+1]; nPoint_Send[0] = 0;
16761  int *nPoint_Recv = new int[size+1]; nPoint_Recv[0] = 0;
16762 
16763  for (int ii=1; ii < size+1; ii++) nPoint_Send[ii]= (int)nSurf_Poin_Par;
16764 
16765 #ifdef HAVE_MPI
16766  SU2_MPI::Alltoall(&(nPoint_Send[1]), 1, MPI_INT,
16767  &(nPoint_Recv[1]), 1, MPI_INT, MPI_COMM_WORLD);
16768 #else
16769  nPoint_Recv[1] = nPoint_Send[1];
16770 #endif
16771 
16772  /*--- Go to cumulative storage format to compute the offsets. ---*/
16773 
16774  for (int ii = 0; ii < size; ii++) {
16775  nPoint_Send[ii+1] += nPoint_Send[ii];
16776  nPoint_Recv[ii+1] += nPoint_Recv[ii];
16777  }
16778 
16779  /*--- Now that we know the number of local surface points that we have,
16780  we can allocate the new data structure to hold these points alone. Here,
16781  we also copy the data for those points from our volume data structure. ---*/
16782 
16783  Parallel_Surf_Data = new su2double*[VARS_PER_POINT];
16784  for (int jj = 0; jj < VARS_PER_POINT; jj++) {
16785  Parallel_Surf_Data[jj] = new su2double[nSurf_Poin_Par];
16786  count = 0;
16787  for (int ii = 0; ii < (int)nParallel_Poin; ii++) {
16788  if (surfPoint[ii] !=-1) {
16789  Parallel_Surf_Data[jj][count] = Parallel_Data[jj][ii];
16790  count++;
16791  }
16792  }
16793  }
16794 
16795  /*--- Reduce the total number of surf points we have. This will be
16796  needed for writing the surface solution files later. ---*/
16797 
16798 #ifndef HAVE_MPI
16799  nGlobal_Surf_Poin = nSurf_Poin_Par;
16800 #else
16801  SU2_MPI::Allreduce(&nSurf_Poin_Par, &nGlobal_Surf_Poin, 1,
16803 #endif
16804 
16805  /*--- Now that we know every proc's global offset for the number of
16806  surface points, we can create the new global numbering. Here, we
16807  create a new mapping using two arrays, which will need to be
16808  communicated. We use our mask again here. ---*/
16809 
16810  unsigned long *globalP = new unsigned long[nSurf_Poin_Par];
16811  unsigned long *renumbP = new unsigned long[nSurf_Poin_Par];
16812 
16813  count = 0;
16814  for (iPoint = 0; iPoint < nParallel_Poin; iPoint++) {
16815  if (surfPoint[iPoint] != -1) {
16816  globalP[count] = surfPoint[iPoint];
16817  renumbP[count] = count + nPoint_Recv[rank];
16818  count++;
16819  }
16820  }
16821 
16822  /*--------------------------------------------------------------------------*/
16823  /*--- Step 3: Communicate the arrays with the new global surface point ---*/
16824  /*--- numbering to the procs that hold the connectivity for ---*/
16825  /*--- each element. This will be done in two phases. First, ---*/
16826  /*--- we send the arrays around to the other procs based on ---*/
16827  /*--- the linear partitioning for the elems. This gets us ---*/
16828  /*--- most of the way there, however, due to the type of ---*/
16829  /*--- linear partitioning for the elements, there may exist ---*/
16830  /*--- elements that have nodes outside of the linear part. ---*/
16831  /*--- bounds. This is because the elems are distributed based ---*/
16832  /*--- on the node with the smallest global ID. ---*/
16833  /*--------------------------------------------------------------------------*/
16834 
16835  /*--- First, we perform the linear partitioning again as it is done
16836  for elements, which is slightly different than for nodes (above). ---*/
16837 
16838  /*--- Force the removal of all added periodic elements (use global index).
16839  First, we isolate and create a list of all added periodic points, excluding
16840  those that were part of the original domain (we want these to be in the
16841  output files). ---*/
16842 
16843  vector<unsigned long> Added_Periodic;
16844  Added_Periodic.clear();
16845 
16846  if (config->GetKind_SU2() != SU2_DEF) {
16847  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
16848  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
16849  SendRecv = config->GetMarker_All_SendRecv(iMarker);
16850  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
16851  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
16852 
16853  if ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
16854  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 0) &&
16855  (SendRecv < 0)) {
16856  Added_Periodic.push_back(geometry->node[iPoint]->GetGlobalIndex());
16857  }
16858  }
16859  }
16860  }
16861  }
16862 
16863  /*--- Now we communicate this information to all processors, so that they
16864  can force the removal of these particular nodes by flagging them as halo
16865  points. In general, this should be a small percentage of the total mesh,
16866  so the communication/storage costs here shouldn't be prohibitive. ---*/
16867 
16868  /*--- First communicate the number of points that each rank has found. ---*/
16869 
16870  unsigned long nAddedPeriodic = 0, maxAddedPeriodic = 0;
16871  unsigned long Buffer_Send_nAddedPeriodic[1], *Buffer_Recv_nAddedPeriodic = NULL;
16872  Buffer_Recv_nAddedPeriodic = new unsigned long[size];
16873 
16874  nAddedPeriodic = Added_Periodic.size();
16875  Buffer_Send_nAddedPeriodic[0] = nAddedPeriodic;
16876 
16877 #ifdef HAVE_MPI
16878  SU2_MPI::Allreduce(&nAddedPeriodic, &maxAddedPeriodic, 1, MPI_UNSIGNED_LONG,
16880  SU2_MPI::Allgather(&Buffer_Send_nAddedPeriodic, 1, MPI_UNSIGNED_LONG,
16881  Buffer_Recv_nAddedPeriodic, 1, MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
16882 #else
16883  maxAddedPeriodic = nAddedPeriodic;
16884  Buffer_Recv_nAddedPeriodic[0] = Buffer_Send_nAddedPeriodic[0];
16885 #endif
16886 
16887  /*--- Communicate the global index values of all added periodic nodes. ---*/
16888  unsigned long *Buffer_Send_AddedPeriodic = new unsigned long[maxAddedPeriodic];
16889  unsigned long *Buffer_Recv_AddedPeriodic = new unsigned long[size*maxAddedPeriodic];
16890 
16891  for (iPoint = 0; iPoint < Added_Periodic.size(); iPoint++) {
16892  Buffer_Send_AddedPeriodic[iPoint] = Added_Periodic[iPoint];
16893  }
16894 
16895  /*--- Gather the element connectivity information. All processors will now
16896  have a copy of the global index values for all added periodic points. ---*/
16897 
16898 #ifdef HAVE_MPI
16899  SU2_MPI::Allgather(Buffer_Send_AddedPeriodic, maxAddedPeriodic, MPI_UNSIGNED_LONG,
16900  Buffer_Recv_AddedPeriodic, maxAddedPeriodic, MPI_UNSIGNED_LONG,
16901  MPI_COMM_WORLD);
16902 #else
16903  for (iPoint = 0; iPoint < maxAddedPeriodic; iPoint++)
16904  Buffer_Recv_AddedPeriodic[iPoint] = Buffer_Send_AddedPeriodic[iPoint];
16905 #endif
16906 
16907  /*--- Search all send/recv boundaries on this partition for halo cells. In
16908  particular, consider only the recv conditions (these are the true halo
16909  nodes). Check the ranks of the processors that are communicating and
16910  choose to keep only the halo cells from the higher rank processor. Here,
16911  we are also choosing to keep periodic nodes that were part of the original
16912  domain. We will check the communicated list of added periodic points. ---*/
16913 
16914  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
16915  Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain();
16916 
16917  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
16918  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
16919  SendRecv = config->GetMarker_All_SendRecv(iMarker);
16920  RecvFrom = abs(SendRecv)-1;
16921 
16922  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
16923  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
16924  Global_Index = geometry->node[iPoint]->GetGlobalIndex();
16925 
16926  /*--- We need to keep one copy of overlapping halo cells. ---*/
16927 
16928  notHalo = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() == 0) &&
16929  (SendRecv < 0) && (rank > RecvFrom));
16930 
16931  /*--- We want to keep the periodic nodes that were part of the original domain.
16932  For SU2_DEF we want to keep all periodic nodes. ---*/
16933 
16934  if (config->GetKind_SU2() == SU2_DEF) {
16935  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0));
16936  }else {
16937  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
16938  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1));
16939  }
16940 
16941  notPeriodic = (isPeriodic && (SendRecv < 0));
16942 
16943  /*--- Lastly, check that this isn't an added periodic point that
16944  we will forcibly remove. Use the communicated list of these points. ---*/
16945 
16946  addedPeriodic = false; kPoint = 0;
16947  for (iProcessor = 0; iProcessor < (unsigned long)size; iProcessor++) {
16948  for (jPoint = 0; jPoint < Buffer_Recv_nAddedPeriodic[iProcessor]; jPoint++) {
16949  if (Global_Index == Buffer_Recv_AddedPeriodic[kPoint+jPoint])
16950  addedPeriodic = true;
16951  }
16952 
16953  /*--- Adjust jNode to index of next proc's data in the buffers. ---*/
16954 
16955  kPoint = (iProcessor+1)*maxAddedPeriodic;
16956 
16957  }
16958 
16959  /*--- If we found either of these types of nodes, flag them to be kept. ---*/
16960 
16961  if ((notHalo || notPeriodic) && !addedPeriodic) {
16962  Local_Halo[iPoint] = false;
16963  }
16964 
16965  }
16966  }
16967  }
16968 
16969  /*--- Now that we've done the gymnastics to find any periodic points,
16970  compute the total number of local and global points for the output. ---*/
16971 
16972  nLocalPoint = 0;
16973  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
16974  if (Local_Halo[iPoint] == false)
16975  nLocalPoint++;
16976 
16977 #ifdef HAVE_MPI
16978  SU2_MPI::Allreduce(&nLocalPoint, &nTotalPoint, 1,
16980 #else
16981  nTotalPoint = nLocalPoint;
16982 #endif
16983 
16984  /*--- Compute the number of points that will be on each processor.
16985  This is a linear partitioning with the addition of a simple load
16986  balancing for any remainder points. ---*/
16987 
16988  total_pt_accounted = 0;
16989  for (int ii = 0; ii < size; ii++) {
16990  npoint_procs[ii] = nTotalPoint/size;
16991  total_pt_accounted = total_pt_accounted + npoint_procs[ii];
16992  }
16993 
16994  /*--- Get the number of remainder points after the even division. ---*/
16995 
16996  rem_points = nTotalPoint-total_pt_accounted;
16997  for (unsigned long ii = 0; ii < rem_points; ii++) {
16998  npoint_procs[ii]++;
16999  }
17000 
17001  /*--- Store the local number of nodes and the beginning/end index ---*/
17002 
17003  starting_node[0] = 0;
17004  ending_node[0] = starting_node[0] + npoint_procs[0];
17005  nPoint_Linear_Elems[0] = 0;
17006  for (int ii = 1; ii < size; ii++) {
17007  starting_node[ii] = ending_node[ii-1];
17008  ending_node[ii] = starting_node[ii] + npoint_procs[ii];
17009  nPoint_Linear_Elems[ii] = nPoint_Linear_Elems[ii-1] + npoint_procs[ii-1];
17010  }
17011  nPoint_Linear_Elems[size] = nTotalPoint;
17012 
17013  /*--- Reset our flags and counters ---*/
17014 
17015  for (int ii=0; ii < size; ii++) {
17016  nElem_Send[ii] = 0;
17017  nElem_Recv[ii] = 0;
17018  nElem_Flag[ii]= -1;
17019  }
17020  nElem_Send[size] = 0; nElem_Recv[size] = 0;
17021 
17022  /*--- Loop through my local surface nodes, find which proc the global
17023  value lives on, then communicate the global ID and remumbered value. ---*/
17024 
17025  for (int ii = 0; ii < (int)nSurf_Poin_Par; ii++) {
17026 
17027  Global_Index = globalP[ii];
17028 
17029  /*--- Search for the processor that owns this point ---*/
17030 
17031  iProcessor = Global_Index/npoint_procs[0];
17032  if (iProcessor >= (unsigned long)size)
17033  iProcessor = (unsigned long)size-1;
17034  if (Global_Index >= nPoint_Linear_Elems[iProcessor])
17035  while(Global_Index >= nPoint_Linear_Elems[iProcessor+1]) iProcessor++;
17036  else
17037  while(Global_Index < nPoint_Linear_Elems[iProcessor]) iProcessor--;
17038 
17039  /*--- If we have not visited this element yet, increment our
17040  number of elements that must be sent to a particular proc. ---*/
17041 
17042  if ((nElem_Flag[iProcessor] != ii)) {
17043  nElem_Flag[iProcessor] = ii;
17044  nElem_Send[iProcessor+1]++;
17045  }
17046 
17047  }
17048 
17049  /*--- Communicate the number of cells to be sent/recv'd amongst
17050  all processors. After this communication, each proc knows how
17051  many cells it will receive from each other processor. ---*/
17052 
17053 #ifdef HAVE_MPI
17054  SU2_MPI::Alltoall(&(nElem_Send[1]), 1, MPI_INT,
17055  &(nElem_Recv[1]), 1, MPI_INT, MPI_COMM_WORLD);
17056 #else
17057  nElem_Recv[1] = nElem_Send[1];
17058 #endif
17059 
17060  /*--- Prepare to send. First check how many
17061  messages we will be sending and receiving. Here we also put
17062  the counters into cumulative storage format to make the
17063  communications simpler. ---*/
17064 
17065  nSends = 0; nRecvs = 0;
17066  for (int ii=0; ii < size; ii++) nElem_Flag[ii] = -1;
17067 
17068  for (int ii = 0; ii < size; ii++) {
17069  if ((ii != rank) && (nElem_Send[ii+1] > 0)) nSends++;
17070  if ((ii != rank) && (nElem_Recv[ii+1] > 0)) nRecvs++;
17071 
17072  nElem_Send[ii+1] += nElem_Send[ii];
17073  nElem_Recv[ii+1] += nElem_Recv[ii];
17074  }
17075 
17076  /*--- Allocate memory to hold the globals that we are
17077  sending. ---*/
17078 
17079  unsigned long *globalSend = NULL;
17080  globalSend = new unsigned long[nElem_Send[size]];
17081  for (int ii = 0; ii < nElem_Send[size]; ii++)
17082  globalSend[ii] = 0;
17083 
17084  /*--- Allocate memory to hold the renumbering that we are
17085  sending. ---*/
17086 
17087  unsigned long *renumbSend = NULL;
17088  renumbSend = new unsigned long[nElem_Send[size]];
17089  for (int ii = 0; ii < nElem_Send[size]; ii++)
17090  renumbSend[ii] = 0;
17091 
17092  /*--- Create an index variable to keep track of our index
17093  position as we load up the send buffer. ---*/
17094 
17095  unsigned long *index = new unsigned long[size];
17096  for (int ii=0; ii < size; ii++) index[ii] = nElem_Send[ii];
17097 
17098  /*--- Loop back through and load up the buffers for the global IDs
17099  and their new renumbering values. ---*/
17100 
17101  for (int ii = 0; ii < (int)nSurf_Poin_Par; ii++) {
17102 
17103  Global_Index = globalP[ii];
17104 
17105  /*--- Search for the processor that owns this point ---*/
17106 
17107  iProcessor = Global_Index/npoint_procs[0];
17108  if (iProcessor >= (unsigned long)size)
17109  iProcessor = (unsigned long)size-1;
17110  if (Global_Index >= nPoint_Linear_Elems[iProcessor])
17111  while(Global_Index >= nPoint_Linear_Elems[iProcessor+1]) iProcessor++;
17112  else
17113  while(Global_Index < nPoint_Linear_Elems[iProcessor]) iProcessor--;
17114 
17115 
17116  if (nElem_Flag[iProcessor] != ii) {
17117 
17118  nElem_Flag[iProcessor] = ii;
17119  unsigned long nn = index[iProcessor];
17120 
17121  globalSend[nn] = Global_Index;
17122  renumbSend[nn] = renumbP[ii];
17123 
17124  /*--- Increment the index by the message length ---*/
17125 
17126  index[iProcessor]++;
17127 
17128  }
17129  }
17130 
17131  /*--- Free memory after loading up the send buffer. ---*/
17132 
17133  delete [] index;
17134 
17135  /*--- Allocate the memory that we need for receiving the
17136  values and then cue up the non-blocking receives. Note that
17137  we do not include our own rank in the communications. We will
17138  directly copy our own data later. ---*/
17139 
17140  unsigned long *globalRecv = NULL;
17141  globalRecv = new unsigned long[nElem_Recv[size]];
17142  for (int ii = 0; ii < nElem_Recv[size]; ii++)
17143  globalRecv[ii] = 0;
17144 
17145  unsigned long *renumbRecv = NULL;
17146  renumbRecv = new unsigned long[nElem_Recv[size]];
17147  for (int ii = 0; ii < nElem_Recv[size]; ii++)
17148  renumbRecv[ii] = 0;
17149 
17150 #ifdef HAVE_MPI
17151  /*--- We need double the number of messages to send both the conn.
17152  and the flags for the halo cells. ---*/
17153 
17154  send_req = new SU2_MPI::Request[2*nSends];
17155  recv_req = new SU2_MPI::Request[2*nRecvs];
17156 
17157  /*--- Launch the non-blocking recv's for the global ID. ---*/
17158 
17159  iMessage = 0;
17160  for (int ii=0; ii<size; ii++) {
17161  if ((ii != rank) && (nElem_Recv[ii+1] > nElem_Recv[ii])) {
17162  int ll = nElem_Recv[ii];
17163  int kk = nElem_Recv[ii+1] - nElem_Recv[ii];
17164  int count = kk;
17165  int source = ii;
17166  int tag = ii + 1;
17167  SU2_MPI::Irecv(&(globalRecv[ll]), count, MPI_UNSIGNED_LONG, source, tag,
17168  MPI_COMM_WORLD, &(recv_req[iMessage]));
17169  iMessage++;
17170  }
17171  }
17172 
17173  /*--- Launch the non-blocking sends of the global ID. ---*/
17174 
17175  iMessage = 0;
17176  for (int ii=0; ii<size; ii++) {
17177  if ((ii != rank) && (nElem_Send[ii+1] > nElem_Send[ii])) {
17178  int ll = nElem_Send[ii];
17179  int kk = nElem_Send[ii+1] - nElem_Send[ii];
17180  int count = kk;
17181  int dest = ii;
17182  int tag = rank + 1;
17183  SU2_MPI::Isend(&(globalSend[ll]), count, MPI_UNSIGNED_LONG, dest, tag,
17184  MPI_COMM_WORLD, &(send_req[iMessage]));
17185  iMessage++;
17186  }
17187  }
17188 
17189  /*--- Launch the non-blocking recv's for the renumbered ID. ---*/
17190 
17191  iMessage = 0;
17192  for (int ii=0; ii<size; ii++) {
17193  if ((ii != rank) && (nElem_Recv[ii+1] > nElem_Recv[ii])) {
17194  int ll = nElem_Recv[ii];
17195  int kk = nElem_Recv[ii+1] - nElem_Recv[ii];
17196  int count = kk;
17197  int source = ii;
17198  int tag = ii + 1;
17199  SU2_MPI::Irecv(&(renumbRecv[ll]), count, MPI_UNSIGNED_LONG, source, tag,
17200  MPI_COMM_WORLD, &(recv_req[iMessage+nRecvs]));
17201  iMessage++;
17202  }
17203  }
17204 
17205  /*--- Launch the non-blocking sends of the renumbered ID. ---*/
17206 
17207  iMessage = 0;
17208  for (int ii=0; ii<size; ii++) {
17209  if ((ii != rank) && (nElem_Send[ii+1] > nElem_Send[ii])) {
17210  int ll = nElem_Send[ii];
17211  int kk = nElem_Send[ii+1] - nElem_Send[ii];
17212  int count = kk;
17213  int dest = ii;
17214  int tag = rank + 1;
17215  SU2_MPI::Isend(&(renumbSend[ll]), count, MPI_UNSIGNED_LONG, dest, tag,
17216  MPI_COMM_WORLD, &(send_req[iMessage+nSends]));
17217  iMessage++;
17218  }
17219  }
17220 
17221 #endif
17222 
17223  /*--- Load our own procs data into the buffers directly. ---*/
17224 
17225  mm = nElem_Recv[rank];
17226  ll = nElem_Send[rank];
17227  kk = nElem_Send[rank+1];
17228 
17229  for (int nn=ll; nn<kk; nn++, mm++) globalRecv[mm] = globalSend[nn];
17230 
17231  mm = nElem_Recv[rank];
17232  ll = nElem_Send[rank];
17233  kk = nElem_Send[rank+1];
17234 
17235  for (int nn=ll; nn<kk; nn++, mm++) renumbRecv[mm] = renumbSend[nn];
17236 
17237  /*--- Wait for the non-blocking sends and recvs to complete. ---*/
17238 
17239 #ifdef HAVE_MPI
17240  number = 2*nSends;
17241  for (int ii = 0; ii < number; ii++)
17242  SU2_MPI::Waitany(number, send_req, &ind, &status);
17243 
17244  number = 2*nRecvs;
17245  for (int ii = 0; ii < number; ii++)
17246  SU2_MPI::Waitany(number, recv_req, &ind, &status);
17247 
17248  delete [] send_req;
17249  delete [] recv_req;
17250 #endif
17251 
17252  /*-- Now update my local connectivitiy for the surface with the new
17253  numbering. Create a new mapping for global -> renumber for nodes. Note
17254  the adding of 1 back in here for the eventual viz. purposes. ---*/
17255 
17256  map<unsigned long,unsigned long> Global2Renumber;
17257  for (int ii = 0; ii < nElem_Recv[size]; ii++) {
17258  Global2Renumber[globalRecv[ii]] = renumbRecv[ii] + 1;
17259  }
17260 
17261 
17262  /*--- The final step is one last pass over all elements to check
17263  for points outside of the linear partitions of the elements. Again,
17264  note that elems were distributed based on their smallest global ID,
17265  so some nodes of the elem may have global IDs lying outside of the
17266  linear partitioning. We need to recover the mapping for these
17267  outliers. We loop over all local surface elements to find these. ---*/
17268 
17269  vector<unsigned long>::iterator it;
17270  vector<unsigned long> outliers;
17271 
17272  for (int ii = 0; ii < (int)nParallel_Line; ii++) {
17273  for ( int jj = 0; jj < N_POINTS_LINE; jj++ ) {
17274 
17275  iNode = ii*N_POINTS_LINE+jj;
17276  Global_Index = Conn_BoundLine_Par[iNode]-1;
17277 
17278  /*--- Search for the processor that owns this point ---*/
17279 
17280  iProcessor = Global_Index/npoint_procs[0];
17281  if (iProcessor >= (unsigned long)size)
17282  iProcessor = (unsigned long)size-1;
17283  if (Global_Index >= nPoint_Linear_Elems[iProcessor])
17284  while(Global_Index >= nPoint_Linear_Elems[iProcessor+1]) iProcessor++;
17285  else
17286  while(Global_Index < nPoint_Linear_Elems[iProcessor]) iProcessor--;
17287 
17288  /*--- Store the global ID if it is outside our own linear partition. ---*/
17289 
17290  if ((iProcessor != (unsigned long)rank)) {
17291  outliers.push_back(Global_Index);
17292  }
17293 
17294  }
17295  }
17296 
17297  for (int ii=0; ii < size; ii++) nElem_Flag[ii]= -1;
17298 
17299  for (int ii = 0; ii < (int)nParallel_BoundTria; ii++) {
17300  for ( int jj = 0; jj < N_POINTS_TRIANGLE; jj++ ) {
17301 
17302  iNode = ii*N_POINTS_TRIANGLE + jj;
17303  Global_Index = Conn_BoundTria_Par[iNode]-1;
17304 
17305  /*--- Search for the processor that owns this point ---*/
17306 
17307  iProcessor = Global_Index/npoint_procs[0];
17308  if (iProcessor >= (unsigned long)size)
17309  iProcessor = (unsigned long)size-1;
17310  if (Global_Index >= nPoint_Linear_Elems[iProcessor])
17311  while(Global_Index >= nPoint_Linear_Elems[iProcessor+1]) iProcessor++;
17312  else
17313  while(Global_Index < nPoint_Linear_Elems[iProcessor]) iProcessor--;
17314 
17315  /*--- Store the global ID if it is outside our own linear partition. ---*/
17316 
17317  if ((iProcessor != (unsigned long)rank)) {
17318  outliers.push_back(Global_Index);
17319  }
17320 
17321  }
17322  }
17323 
17324  for (int ii=0; ii < size; ii++) nElem_Flag[ii]= -1;
17325 
17326  for (int ii = 0; ii < (int)nParallel_BoundQuad; ii++) {
17327  for ( int jj = 0; jj < N_POINTS_QUADRILATERAL; jj++ ) {
17328 
17329  iNode = ii*N_POINTS_QUADRILATERAL+jj;
17330  Global_Index = Conn_BoundQuad_Par[iNode]-1;
17331 
17332  /*--- Search for the processor that owns this point ---*/
17333 
17334  iProcessor = Global_Index/npoint_procs[0];
17335  if (iProcessor >= (unsigned long)size)
17336  iProcessor = (unsigned long)size-1;
17337  if (Global_Index >= nPoint_Linear_Elems[iProcessor])
17338  while(Global_Index >= nPoint_Linear_Elems[iProcessor+1]) iProcessor++;
17339  else
17340  while(Global_Index < nPoint_Linear_Elems[iProcessor]) iProcessor--;
17341 
17342  /*--- Store the global ID if it is outside our own linear partition. ---*/
17343 
17344  if ((iProcessor != (unsigned long)rank)) {
17345  outliers.push_back(Global_Index);
17346  }
17347 
17348  }
17349  }
17350 
17351  /*--- Create a unique list of global IDs that fall outside of our procs
17352  linear partition. ---*/
17353 
17354  sort(outliers.begin(), outliers.end());
17355  it = unique(outliers.begin(), outliers.end());
17356  outliers.resize(it - outliers.begin());
17357 
17358  /*--- Now loop over the outliers and communicate to those procs that
17359  hold the new numbering for our outlier points. We need to ask for the
17360  new numbering from these procs. ---*/
17361 
17362  for (int ii=0; ii < size; ii++) {
17363  nElem_Send[ii] = 0;
17364  nElem_Recv[ii] = 0;
17365  nElem_Flag[ii]= -1;
17366  }
17367  nElem_Send[size] = 0; nElem_Recv[size] = 0;
17368 
17369  for (int ii = 0; ii < (int)outliers.size(); ii++) {
17370 
17371  Global_Index = outliers[ii];
17372 
17373  /*--- Search for the processor that owns this point ---*/
17374 
17375  iProcessor = Global_Index/npoint_procs[0];
17376  if (iProcessor >= (unsigned long)size)
17377  iProcessor = (unsigned long)size-1;
17378  if (Global_Index >= nPoint_Linear_Nodes[iProcessor])
17379  while(Global_Index >= nPoint_Linear_Nodes[iProcessor+1]) iProcessor++;
17380  else
17381  while(Global_Index < nPoint_Linear_Nodes[iProcessor]) iProcessor--;
17382 
17383  /*--- If we have not visited this element yet, increment our
17384  number of elements that must be sent to a particular proc. ---*/
17385 
17386  if ((nElem_Flag[iProcessor] != ii)) {
17387  nElem_Flag[iProcessor] = ii;
17388  nElem_Send[iProcessor+1]++;
17389  }
17390 
17391  }
17392 
17393  /*--- Communicate the number of cells to be sent/recv'd amongst
17394  all processors. After this communication, each proc knows how
17395  many cells it will receive from each other processor. ---*/
17396 
17397 #ifdef HAVE_MPI
17398  SU2_MPI::Alltoall(&(nElem_Send[1]), 1, MPI_INT,
17399  &(nElem_Recv[1]), 1, MPI_INT, MPI_COMM_WORLD);
17400 #else
17401  nElem_Recv[1] = nElem_Send[1];
17402 #endif
17403 
17404  /*--- Prepare to send connectivities. First check how many
17405  messages we will be sending and receiving. Here we also put
17406  the counters into cumulative storage format to make the
17407  communications simpler. ---*/
17408 
17409  nSends = 0; nRecvs = 0;
17410  for (int ii=0; ii < size; ii++) nElem_Flag[ii] = -1;
17411 
17412  for (int ii = 0; ii < size; ii++) {
17413  if ((ii != rank) && (nElem_Send[ii+1] > 0)) nSends++;
17414  if ((ii != rank) && (nElem_Recv[ii+1] > 0)) nRecvs++;
17415 
17416  nElem_Send[ii+1] += nElem_Send[ii];
17417  nElem_Recv[ii+1] += nElem_Recv[ii];
17418  }
17419 
17420  delete [] idSend;
17421  idSend = new unsigned long[nElem_Send[size]];
17422  for (int ii = 0; ii < nElem_Send[size]; ii++)
17423  idSend[ii] = 0;
17424 
17425  /*--- Reset our index variable for reuse. ---*/
17426 
17427  for (int ii=0; ii < size; ii++) idIndex[ii] = nElem_Send[ii];
17428 
17429  /*--- Loop over the outliers again and load up the global IDs. ---*/
17430 
17431  for (int ii = 0; ii < (int)outliers.size(); ii++) {
17432 
17433  Global_Index = outliers[ii];
17434 
17435  /*--- Search for the processor that owns this point ---*/
17436 
17437  iProcessor = Global_Index/npoint_procs[0];
17438  if (iProcessor >= (unsigned long)size)
17439  iProcessor = (unsigned long)size-1;
17440  if (Global_Index >= nPoint_Linear_Nodes[iProcessor])
17441  while(Global_Index >= nPoint_Linear_Nodes[iProcessor+1]) iProcessor++;
17442  else
17443  while(Global_Index < nPoint_Linear_Nodes[iProcessor]) iProcessor--;
17444 
17445  /*--- If we have not visited this element yet, increment our
17446  number of elements that must be sent to a particular proc. ---*/
17447 
17448  if ((nElem_Flag[iProcessor] != ii)) {
17449 
17450  nElem_Flag[iProcessor] = ii;
17451  unsigned long nn = idIndex[iProcessor];
17452 
17453  /*--- Load the global ID values. ---*/
17454 
17455  idSend[nn] = Global_Index; nn++;
17456 
17457  /*--- Increment the index by the message length ---*/
17458 
17459  idIndex[iProcessor]++;
17460 
17461  }
17462  }
17463 
17464  /*--- Allocate the memory that we need for receiving the
17465  values and then cue up the non-blocking receives. Note that
17466  we do not include our own rank in the communications. We will
17467  directly copy our own data later. ---*/
17468 
17469  delete [] idRecv;
17470  idRecv = new unsigned long[nElem_Recv[size]];
17471  for (int ii = 0; ii < nElem_Recv[size]; ii++)
17472  idRecv[ii] = 0;
17473 
17474 #ifdef HAVE_MPI
17475  /*--- We need double the number of messages to send both the conn.
17476  and the flags for the halo cells. ---*/
17477 
17478  send_req = new SU2_MPI::Request[nSends];
17479  recv_req = new SU2_MPI::Request[nRecvs];
17480 
17481  /*--- Launch the non-blocking recv's for the connectivity. ---*/
17482 
17483  iMessage = 0;
17484  for (int ii=0; ii<size; ii++) {
17485  if ((ii != rank) && (nElem_Recv[ii+1] > nElem_Recv[ii])) {
17486  int ll = nElem_Recv[ii];
17487  int kk = nElem_Recv[ii+1] - nElem_Recv[ii];
17488  int count = kk;
17489  int source = ii;
17490  int tag = ii + 1;
17491  SU2_MPI::Irecv(&(idRecv[ll]), count, MPI_UNSIGNED_LONG, source, tag,
17492  MPI_COMM_WORLD, &(recv_req[iMessage]));
17493  iMessage++;
17494  }
17495  }
17496 
17497  /*--- Launch the non-blocking sends of the connectivity. ---*/
17498 
17499  iMessage = 0;
17500  for (int ii=0; ii<size; ii++) {
17501  if ((ii != rank) && (nElem_Send[ii+1] > nElem_Send[ii])) {
17502  int ll = nElem_Send[ii];
17503  int kk = nElem_Send[ii+1] - nElem_Send[ii];
17504  int count = kk;
17505  int dest = ii;
17506  int tag = rank + 1;
17507  SU2_MPI::Isend(&(idSend[ll]), count, MPI_UNSIGNED_LONG, dest, tag,
17508  MPI_COMM_WORLD, &(send_req[iMessage]));
17509  iMessage++;
17510  }
17511  }
17512 #endif
17513 
17514  /*--- Copy my own rank's data into the recv buffer directly. ---*/
17515 
17516  mm = nElem_Recv[rank];
17517  ll = nElem_Send[rank];
17518  kk = nElem_Send[rank+1];
17519 
17520  for (int nn=ll; nn<kk; nn++, mm++) idRecv[mm] = idSend[nn];
17521 
17522  /*--- Wait for the non-blocking sends and recvs to complete. ---*/
17523 
17524 #ifdef HAVE_MPI
17525  number = nSends;
17526  for (int ii = 0; ii < number; ii++)
17527  SU2_MPI::Waitany(number, send_req, &ind, &status);
17528 
17529  number = nRecvs;
17530  for (int ii = 0; ii < number; ii++)
17531  SU2_MPI::Waitany(number, recv_req, &ind, &status);
17532 
17533  delete [] send_req;
17534  delete [] recv_req;
17535 #endif
17536 
17537  /*--- The procs holding the outlier grid nodes now have the global IDs
17538  that they need to have their renumbering shared. ---*/
17539 
17540  for (int ii = 0; ii < nElem_Recv[size]; ii++) {
17541  for (iPoint = 0; iPoint < nSurf_Poin_Par; iPoint++) {
17542  if (idRecv[ii] == globalP[iPoint]) {
17543  idRecv[ii] = renumbP[iPoint];
17544  }
17545  }
17546  }
17547 
17548  /*--- Now simply reverse the last communication to give the renumbered IDs
17549  back to the owner of the outlier points. Note everything is flipped. ---*/
17550 
17551 #ifdef HAVE_MPI
17552  /*--- We need double the number of messages to send both the conn.
17553  and the flags for the halo cells. ---*/
17554 
17555  send_req = new SU2_MPI::Request[nRecvs];
17556  recv_req = new SU2_MPI::Request[nSends];
17557 
17558  /*--- Launch the non-blocking sends of the connectivity. ---*/
17559 
17560  iMessage = 0;
17561  for (int ii=0; ii<size; ii++) {
17562  if ((ii != rank) && (nElem_Send[ii+1] > nElem_Send[ii])) {
17563  int ll = nElem_Send[ii];
17564  int kk = nElem_Send[ii+1] - nElem_Send[ii];
17565  int count = kk;
17566  int dest = ii;
17567  int tag = ii + 1;
17568  SU2_MPI::Irecv(&(idSend[ll]), count, MPI_UNSIGNED_LONG, dest, tag,
17569  MPI_COMM_WORLD, &(recv_req[iMessage]));
17570  iMessage++;
17571  }
17572  }
17573 
17574  /*--- Launch the non-blocking recv's for the connectivity. ---*/
17575 
17576  iMessage = 0;
17577  for (int ii=0; ii<size; ii++) {
17578  if ((ii != rank) && (nElem_Recv[ii+1] > nElem_Recv[ii])) {
17579  int ll = nElem_Recv[ii];
17580  int kk = nElem_Recv[ii+1] - nElem_Recv[ii];
17581  int count = kk;
17582  int source = ii;
17583  int tag = rank + 1;
17584  SU2_MPI::Isend(&(idRecv[ll]), count, MPI_UNSIGNED_LONG, source, tag,
17585  MPI_COMM_WORLD, &(send_req[iMessage]));
17586  iMessage++;
17587  }
17588  }
17589 #endif
17590 
17591  /*--- Copy my own rank's data into the recv buffer directly. ---*/
17592 
17593  mm = nElem_Send[rank];
17594  ll = nElem_Recv[rank];
17595  kk = nElem_Recv[rank+1];
17596 
17597  for (int nn=ll; nn<kk; nn++, mm++) idSend[mm] = idRecv[nn];
17598 
17599  /*--- Wait for the non-blocking sends and recvs to complete. ---*/
17600 
17601 #ifdef HAVE_MPI
17602  number = nRecvs;
17603  for (int ii = 0; ii < number; ii++)
17604  SU2_MPI::Waitany(number, send_req, &ind, &status);
17605 
17606  number = nSends;
17607  for (int ii = 0; ii < number; ii++)
17608  SU2_MPI::Waitany(number, recv_req, &ind, &status);
17609 
17610  delete [] send_req;
17611  delete [] recv_req;
17612 #endif
17613 
17614  /*--- Add the renumbering for the outliers to the map from before carrying
17615  the global -> renumber transformation. Note that by construction,
17616  nElem_Send[ii] == outliers.size(). We also add in the 1 for viz. here. ---*/
17617 
17618  for (int ii = 0; ii < nElem_Send[size]; ii++) {
17619  Global2Renumber[outliers[ii]] = idSend[ii] + 1;
17620  }
17621 
17622  /*--- We can now overwrite the local connectivity for our surface elems
17623  using our completed map with the new global renumbering. Whew!! Note
17624  the -1 when accessing the conn from the map. ---*/
17625 
17626  for (iElem = 0; iElem < nParallel_Line; iElem++) {
17627  iNode = (int)iElem*N_POINTS_LINE;
17628  Conn_BoundLine_Par[iNode+0] = (int)Global2Renumber[Conn_BoundLine_Par[iNode+0]-1];
17629  Conn_BoundLine_Par[iNode+1] = (int)Global2Renumber[Conn_BoundLine_Par[iNode+1]-1];
17630  }
17631 
17632  for (iElem = 0; iElem < nParallel_BoundTria; iElem++) {
17633  iNode = (int)iElem*N_POINTS_TRIANGLE;
17634  Conn_BoundTria_Par[iNode+0] = (int)Global2Renumber[Conn_BoundTria_Par[iNode+0]-1];
17635  Conn_BoundTria_Par[iNode+1] = (int)Global2Renumber[Conn_BoundTria_Par[iNode+1]-1];
17636  Conn_BoundTria_Par[iNode+2] = (int)Global2Renumber[Conn_BoundTria_Par[iNode+2]-1];
17637  }
17638 
17639  for (iElem = 0; iElem < nParallel_BoundQuad; iElem++) {
17640  iNode = (int)iElem*N_POINTS_QUADRILATERAL;
17641  Conn_BoundQuad_Par[iNode+0] = (int)Global2Renumber[Conn_BoundQuad_Par[iNode+0]-1];
17642  Conn_BoundQuad_Par[iNode+1] = (int)Global2Renumber[Conn_BoundQuad_Par[iNode+1]-1];
17643  Conn_BoundQuad_Par[iNode+2] = (int)Global2Renumber[Conn_BoundQuad_Par[iNode+2]-1];
17644  Conn_BoundQuad_Par[iNode+3] = (int)Global2Renumber[Conn_BoundQuad_Par[iNode+3]-1];
17645  }
17646 
17647  /*--- Free temporary memory ---*/
17648 
17649  delete [] idIndex;
17650  delete [] surfPoint;
17651  delete [] globalP;
17652  delete [] renumbP;
17653 
17654  delete [] idSend;
17655  delete [] idRecv;
17656  delete [] globalSend;
17657  delete [] globalRecv;
17658  delete [] renumbSend;
17659  delete [] renumbRecv;
17660  delete [] nElem_Recv;
17661  delete [] nElem_Send;
17662  delete [] nElem_Flag;
17663  delete [] Local_Halo;
17664  delete [] Buffer_Recv_nAddedPeriodic;
17665  delete [] Buffer_Send_AddedPeriodic;
17666  delete [] Buffer_Recv_AddedPeriodic;
17667  delete [] npoint_procs;
17668  delete [] starting_node;
17669  delete [] ending_node;
17670  delete [] nPoint_Linear_Elems;
17671  delete [] nPoint_Linear_Nodes;
17672  delete [] nPoint_Send;
17673  delete [] nPoint_Recv;
17674 
17675 }
17676 
17677 void COutputLegacy::WriteRestart_Parallel_ASCII(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone, unsigned short val_iInst) {
17678 
17679  /*--- Local variables ---*/
17680 
17681  unsigned short nZone = geometry->GetnZone(), nInst = config->GetnTimeInstances();
17682  unsigned short iVar;
17683  unsigned long iPoint, iExtIter = config->GetInnerIter();
17684  bool fem = (config->GetKind_Solver() == FEM_ELASTICITY);
17685  bool disc_adj_fem = (config->GetKind_Solver() == DISC_ADJ_FEM);
17686  bool adjoint = (config->GetContinuous_Adjoint() ||
17687  config->GetDiscrete_Adjoint());
17688  ofstream restart_file;
17689  string filename;
17690 
17691  int iProcessor;
17692 
17693  /*--- Retrieve filename from config ---*/
17694 
17695 // if ((config->GetContinuous_Adjoint()) || (config->GetDiscrete_Adjoint())) {
17696 // filename = config->GetRestart_AdjFileName();
17697 // filename = config->GetObjFunc_Extension(filename);
17698 // } else if (fem) {
17699 // filename = config->GetRestart_FEMFileName();
17700 // } else if (disc_adj_fem){
17701 // filename = config->GetRestart_AdjFEMFileName();
17702 // } else {
17703 // filename = config->GetRestart_FileName();
17704 // }
17705 
17706  /*--- Append the zone number if multizone problems ---*/
17707  if (nZone > 1)
17708  filename= config->GetMultizone_FileName(filename, val_iZone, ".dat");
17709 
17710  /*--- Append the zone number if multiple instance problems ---*/
17711  if (nInst > 1)
17712  filename= config->GetMultiInstance_FileName(filename, val_iInst, ".dat");
17713 
17714  /*--- Unsteady problems require an iteration number to be appended. ---*/
17715  if (config->GetTime_Marching() == HARMONIC_BALANCE) {
17716  filename = config->GetUnsteady_FileName(filename, SU2_TYPE::Int(val_iInst), ".dat");
17717  } else if (config->GetTime_Domain()) {
17718  filename = config->GetUnsteady_FileName(filename, SU2_TYPE::Int(iExtIter), ".dat");
17719  } else if ((fem || disc_adj_fem) && (config->GetWrt_Dynamic())) {
17720  filename = config->GetUnsteady_FileName(filename, SU2_TYPE::Int(iExtIter), ".dat");
17721  }
17722 
17723  /*--- Only the master node writes the header. ---*/
17724 
17725  if (rank == MASTER_NODE) {
17726  restart_file.open(filename.c_str(), ios::out);
17727  restart_file.precision(15);
17728  restart_file << "\"PointID\"";
17729  for (iVar = 0; iVar < Variable_Names.size()-1; iVar++)
17730  restart_file << "\t\"" << Variable_Names[iVar] << "\"";
17731  restart_file << "\t\"" << Variable_Names[Variable_Names.size()-1] << "\"" << endl;
17732  restart_file.close();
17733  }
17734 
17735 #ifdef HAVE_MPI
17737 #endif
17738 
17739  /*--- All processors open the file. ---*/
17740 
17741  restart_file.open(filename.c_str(), ios::out | ios::app);
17742  restart_file.precision(15);
17743 
17744  /*--- Write the restart file in parallel, processor by processor. ---*/
17745 
17746  unsigned long myPoint = 0, offset = 0, Global_Index;
17747  for (iProcessor = 0; iProcessor < size; iProcessor++) {
17748  if (rank == iProcessor) {
17749  for (iPoint = 0; iPoint < nParallel_Poin; iPoint++) {
17750 
17751  /*--- Global Index of the current point. (note outer loop over procs) ---*/
17752 
17753  Global_Index = iPoint + offset;
17754 
17755  /*--- Only write original domain points, i.e., exclude any periodic
17756  or halo nodes, even if they are output in the viz. files. ---*/
17757 
17758  if (Global_Index < nPoint_Restart) {
17759 
17760  /*--- Write global index. (note outer loop over procs) ---*/
17761 
17762  restart_file << Global_Index << "\t";
17763  myPoint++;
17764 
17765  /*--- Loop over the variables and write the values to file ---*/
17766 
17767  for (iVar = 0; iVar < nVar_Par; iVar++) {
17768  restart_file << scientific << Parallel_Data[iVar][iPoint] << "\t";
17769  }
17770  restart_file << "\n";
17771  }
17772  }
17773  }
17774  /*--- Flush the file and wait for all processors to arrive. ---*/
17775  restart_file.flush();
17776 #ifdef HAVE_MPI
17779 #endif
17780 
17781  }
17782 
17783  /*--- Write the metadata (master rank alone) ----*/
17784 
17785  if (rank == MASTER_NODE) {
17786 // if (dual_time)
17787  restart_file <<"EXT_ITER= " << config->GetInnerIter() + 1 << endl;
17788 // else
17789 // restart_file <<"EXT_ITER= " << config->GetInnerIter() + config->GetInnerIter_OffSet() + 1 << endl;
17790  restart_file <<"AOA= " << config->GetAoA() - config->GetAoA_Offset() << endl;
17791  restart_file <<"SIDESLIP_ANGLE= " << config->GetAoS() - config->GetAoS_Offset() << endl;
17792  restart_file <<"INITIAL_BCTHRUST= " << config->GetInitial_BCThrust() << endl;
17793  restart_file <<"DCD_DCL_VALUE= " << config->GetdCD_dCL() << endl;
17794  restart_file <<"DCMX_DCL_VALUE= " << config->GetdCMx_dCL() << endl;
17795  restart_file <<"DCMY_DCL_VALUE= " << config->GetdCMy_dCL() << endl;
17796  restart_file <<"DCMZ_DCL_VALUE= " << config->GetdCMz_dCL() << endl;
17797 
17798  if (((config->GetKind_Solver() == DISC_ADJ_EULER) ||
17799  (config->GetKind_Solver() == DISC_ADJ_NAVIER_STOKES) ||
17800  (config->GetKind_Solver() == DISC_ADJ_RANS) ||
17801  (config->GetKind_Solver() == DISC_ADJ_INC_EULER) ||
17802  (config->GetKind_Solver() == DISC_ADJ_INC_NAVIER_STOKES) ||
17803  (config->GetKind_Solver() == DISC_ADJ_INC_RANS)) && adjoint) {
17804  restart_file << "SENS_AOA=" << solver[ADJFLOW_SOL]->GetTotal_Sens_AoA() * PI_NUMBER / 180.0 << endl;
17805  }
17806  }
17807 
17808  /*--- All processors close the file. ---*/
17809 
17810  restart_file.close();
17811 
17812 }
17813 
17814 void COutputLegacy::WriteRestart_Parallel_Binary(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone, unsigned short val_iInst) {
17815 
17816  /*--- Local variables ---*/
17817 
17818  unsigned short iVar, nZone = geometry->GetnZone(), nInst = config->GetnTimeInstances();
17819  unsigned long iPoint, iExtIter = config->GetInnerIter();
17820  bool fem = (config->GetKind_Solver() == FEM_ELASTICITY);
17821  bool adjoint = (config->GetContinuous_Adjoint() ||
17822  config->GetDiscrete_Adjoint());
17823  bool dual_time = ((config->GetTime_Marching() == DT_STEPPING_1ST) ||
17824  (config->GetTime_Marching() == DT_STEPPING_2ND));
17825  bool wrt_perf = config->GetWrt_Performance();
17826  ofstream restart_file;
17827  string filename;
17828  char str_buf[CGNS_STRING_SIZE], fname[100];
17829  su2double file_size = 0.0, StartTime, StopTime, UsedTime, Bandwidth;
17830 
17831  /*--- Retrieve filename from config ---*/
17832 
17833 // if ((config->GetContinuous_Adjoint()) || (config->GetDiscrete_Adjoint())) {
17834 // filename = config->GetRestart_AdjFileName();
17835 // filename = config->GetObjFunc_Extension(filename);
17836 // } else if (fem) {
17837 // filename = config->GetRestart_FEMFileName();
17838 // } else {
17839 // filename = config->GetRestart_FileName();
17840 // }
17841 
17842  /*--- Append the zone number if multizone problems ---*/
17843  if (nZone > 1)
17844  filename= config->GetMultizone_FileName(filename, val_iZone, ".dat");
17845 
17846  /*--- Append the zone number if multiple instance problems ---*/
17847  if (nInst > 1)
17848  filename= config->GetMultiInstance_FileName(filename, val_iInst, ".dat");
17849 
17850  /*--- Unsteady problems require an iteration number to be appended. ---*/
17851  if (config->GetTime_Marching() == HARMONIC_BALANCE) {
17852  filename = config->GetUnsteady_FileName(filename, SU2_TYPE::Int(val_iInst), ".dat");
17853  } else if (config->GetTime_Domain()) {
17854  filename = config->GetUnsteady_FileName(filename, SU2_TYPE::Int(iExtIter), ".dat");
17855  } else if ((fem) && (config->GetWrt_Dynamic())) {
17856  filename = config->GetUnsteady_FileName(filename, SU2_TYPE::Int(iExtIter), ".dat");
17857  }
17858 
17859  strcpy(fname, filename.c_str());
17860 
17861  /*--- Prepare the first ints containing the counts. The first is a
17862  magic number that we can use to check for binary files (it is the hex
17863  representation for "SU2"). The second two values are number of variables
17864  and number of points (DoFs). The last two values are for metadata:
17865  one int for ExtIter and 8 su2doubles. ---*/
17866 
17867  int var_buf_size = 5;
17868  int var_buf[5] = {535532, nVar_Par, (int)nGlobalPoint_Sort, 1, 8};
17869 
17870  /*--- Prepare the 1D data buffer on this rank. ---*/
17871 
17872  passivedouble *buf = new passivedouble[nParallel_Poin*nVar_Par];
17873 
17874  /*--- For now, create a temp 1D buffer to load up the data for writing.
17875  This will be replaced with a derived data type most likely. ---*/
17876 
17877  for (iPoint = 0; iPoint < nParallel_Poin; iPoint++)
17878  for (iVar = 0; iVar < nVar_Par; iVar++)
17879  buf[iPoint*nVar_Par+iVar] = SU2_TYPE::GetValue(Parallel_Data[iVar][iPoint]);
17880 
17881  /*--- Prepare metadata. ---*/
17882 
17883  int Restart_ExtIter;
17884  if (dual_time)
17885  Restart_ExtIter= (int)config->GetInnerIter() + 1;
17886  else
17887  Restart_ExtIter = (int)config->GetInnerIter() + (int)config->GetExtIter_OffSet() + 1;
17888 
17889  passivedouble Restart_Metadata[8] = {
17890  SU2_TYPE::GetValue(config->GetAoA() - config->GetAoA_Offset()),
17891  SU2_TYPE::GetValue(config->GetAoS() - config->GetAoS_Offset()),
17893  SU2_TYPE::GetValue(config->GetdCD_dCL()),
17894  SU2_TYPE::GetValue(config->GetdCMx_dCL()),
17895  SU2_TYPE::GetValue(config->GetdCMy_dCL()),
17896  SU2_TYPE::GetValue(config->GetdCMz_dCL()),
17897  0.0
17898  };
17899 
17900  if (((config->GetKind_Solver() == DISC_ADJ_EULER) ||
17901  (config->GetKind_Solver() == DISC_ADJ_NAVIER_STOKES) ||
17902  (config->GetKind_Solver() == DISC_ADJ_RANS) ||
17903  (config->GetKind_Solver() == DISC_ADJ_INC_EULER) ||
17904  (config->GetKind_Solver() == DISC_ADJ_INC_NAVIER_STOKES) ||
17905  (config->GetKind_Solver() == DISC_ADJ_INC_RANS)) && adjoint) {
17906  Restart_Metadata[4] = SU2_TYPE::GetValue(solver[ADJFLOW_SOL]->GetTotal_Sens_AoA() * PI_NUMBER / 180.0);
17907  }
17908 
17909  /*--- Set a timer for the binary file writing. ---*/
17910 
17911 #ifndef HAVE_MPI
17912  StartTime = su2double(clock())/su2double(CLOCKS_PER_SEC);
17913 #else
17914  StartTime = MPI_Wtime();
17915 #endif
17916 
17917 #ifndef HAVE_MPI
17918 
17919  FILE* fhw;
17920  fhw = fopen(fname, "wb");
17921 
17922  /*--- Error check for opening the file. ---*/
17923 
17924  if (!fhw) {
17925  SU2_MPI::Error(string("Unable to open SU2 restart file ") + string(fname), CURRENT_FUNCTION);
17926  }
17927 
17928  /*--- First, write the number of variables and points. ---*/
17929 
17930  fwrite(var_buf, var_buf_size, sizeof(int), fhw);
17931  file_size += (su2double)var_buf_size*sizeof(int);
17932 
17933  /*--- Write the variable names to the file. Note that we are adopting a
17934  fixed length of 33 for the string length to match with CGNS. This is
17935  needed for when we read the strings later. ---*/
17936 
17937  for (iVar = 0; iVar < nVar_Par; iVar++) {
17938  strncpy(str_buf, Variable_Names[iVar].c_str(), CGNS_STRING_SIZE);
17939  fwrite(str_buf, CGNS_STRING_SIZE, sizeof(char), fhw);
17940  file_size += (su2double)CGNS_STRING_SIZE*sizeof(char);
17941  }
17942 
17943  /*--- Call to write the entire restart file data in binary in one shot. ---*/
17944 
17945  fwrite(buf, nVar_Par*nParallel_Poin, sizeof(passivedouble), fhw);
17946  file_size += (su2double)nVar_Par*nParallel_Poin*sizeof(passivedouble);
17947 
17948  /*--- Write the external iteration. ---*/
17949 
17950  fwrite(&Restart_ExtIter, 1, sizeof(int), fhw);
17951  file_size += (su2double)sizeof(int);
17952 
17953  /*--- Write the metadata. ---*/
17954 
17955  fwrite(Restart_Metadata, 8, sizeof(passivedouble), fhw);
17956  file_size += (su2double)8*sizeof(passivedouble);
17957 
17958  /*--- Close the file. ---*/
17959 
17960  fclose(fhw);
17961 
17962 #else
17963 
17964  /*--- Parallel binary output using MPI I/O. ---*/
17965 
17966  MPI_File fhw;
17967  SU2_MPI::Status status;
17968  MPI_Datatype etype, filetype;
17969  MPI_Offset disp;
17970  int ierr;
17971 
17972  /*--- We're writing only su2doubles in the data portion of the file. ---*/
17973 
17974  etype = MPI_DOUBLE;
17975 
17976  /*--- Define a derived datatype for this ranks contiguous chunk of data
17977  that will be placed in the restart (1D array size = num points * num vars). ---*/
17978 
17979  MPI_Type_contiguous(nVar_Par*nParallel_Poin, MPI_DOUBLE, &filetype);
17980  MPI_Type_commit(&filetype);
17981 
17982  /*--- All ranks open the file using MPI. Here, we try to open the file with
17983  exclusive so that an error is generated if the file exists. We always want
17984  to write a fresh restart file, so we delete any existing files and create
17985  a new one. ---*/
17986 
17987  ierr = MPI_File_open(MPI_COMM_WORLD, fname,
17988  MPI_MODE_CREATE|MPI_MODE_EXCL|MPI_MODE_WRONLY,
17989  MPI_INFO_NULL, &fhw);
17990  if (ierr != MPI_SUCCESS) {
17991  MPI_File_close(&fhw);
17992  if (rank == 0)
17993  MPI_File_delete(fname, MPI_INFO_NULL);
17994  ierr = MPI_File_open(MPI_COMM_WORLD, fname,
17995  MPI_MODE_CREATE|MPI_MODE_EXCL|MPI_MODE_WRONLY,
17996  MPI_INFO_NULL, &fhw);
17997  }
17998 
17999  /*--- Error check opening the file. ---*/
18000 
18001  if (ierr) {
18002  SU2_MPI::Error(string("Unable to open SU2 restart file ") + string(fname), CURRENT_FUNCTION);
18003  }
18004 
18005  /*--- First, write the number of variables and points (i.e., cols and rows),
18006  which we will need in order to read the file later. Also, write the
18007  variable string names here. Only the master rank writes the header. ---*/
18008 
18009  if (rank == MASTER_NODE) {
18010  MPI_File_write(fhw, var_buf, var_buf_size, MPI_INT, MPI_STATUS_IGNORE);
18011  file_size += (su2double)var_buf_size*sizeof(int);
18012 
18013  /*--- Write the variable names to the file. Note that we are adopting a
18014  fixed length of 33 for the string length to match with CGNS. This is
18015  needed for when we read the strings later. ---*/
18016 
18017  for (iVar = 0; iVar < nVar_Par; iVar++) {
18018  disp = var_buf_size*sizeof(int) + iVar*CGNS_STRING_SIZE*sizeof(char);
18019  strncpy(str_buf, Variable_Names[iVar].c_str(), CGNS_STRING_SIZE);
18020  MPI_File_write_at(fhw, disp, str_buf, CGNS_STRING_SIZE, MPI_CHAR, MPI_STATUS_IGNORE);
18021  file_size += (su2double)CGNS_STRING_SIZE*sizeof(char);
18022  }
18023  }
18024 
18025  /*--- Compute the offset for this rank's linear partition of the data in bytes.
18026  After the calculations above, we have the partition sizes store in nPoint_Linear
18027  in cumulative storage format. ---*/
18028 
18029  disp = (var_buf_size*sizeof(int) + nVar_Par*CGNS_STRING_SIZE*sizeof(char) +
18030  nVar_Par*nPointCumulative[rank]*sizeof(passivedouble));
18031 
18032  /*--- Set the view for the MPI file write, i.e., describe the location in
18033  the file that this rank "sees" for writing its piece of the restart file. ---*/
18034 
18035  MPI_File_set_view(fhw, disp, etype, filetype, (char*)"native", MPI_INFO_NULL);
18036 
18037  /*--- Collective call for all ranks to write to their view simultaneously. ---*/
18038 
18039  MPI_File_write_all(fhw, buf, nVar_Par*nParallel_Poin, MPI_DOUBLE, &status);
18040  file_size += (su2double)nVar_Par*nParallel_Poin*sizeof(passivedouble);
18041 
18042  /*--- Free the derived datatype. ---*/
18043 
18044  MPI_Type_free(&filetype);
18045 
18046  /*--- Reset the file view before writing the metadata. ---*/
18047 
18048  MPI_File_set_view(fhw, 0, MPI_BYTE, MPI_BYTE, (char*)"native", MPI_INFO_NULL);
18049 
18050  /*--- Finally, the master rank writes the metadata. ---*/
18051 
18052  if (rank == MASTER_NODE) {
18053 
18054  /*--- External iteration. ---*/
18055 
18056  disp = (var_buf_size*sizeof(int) + nVar_Par*CGNS_STRING_SIZE*sizeof(char) +
18057  nVar_Par*nGlobalPoint_Sort*sizeof(passivedouble));
18058  MPI_File_write_at(fhw, disp, &Restart_ExtIter, 1, MPI_INT, MPI_STATUS_IGNORE);
18059  file_size += (su2double)sizeof(int);
18060 
18061  /*--- Additional doubles for AoA, AoS, etc. ---*/
18062 
18063  disp = (var_buf_size*sizeof(int) + nVar_Par*CGNS_STRING_SIZE*sizeof(char) +
18064  nVar_Par*nGlobalPoint_Sort*sizeof(passivedouble) + 1*sizeof(int));
18065  MPI_File_write_at(fhw, disp, Restart_Metadata, 8, MPI_DOUBLE, MPI_STATUS_IGNORE);
18066  file_size += (su2double)8*sizeof(passivedouble);
18067 
18068  }
18069 
18070  /*--- All ranks close the file after writing. ---*/
18071 
18072  MPI_File_close(&fhw);
18073 
18074 #endif
18075 
18076  /*--- Compute and store the write time. ---*/
18077 
18078 #ifndef HAVE_MPI
18079  StopTime = su2double(clock())/su2double(CLOCKS_PER_SEC);
18080 #else
18081  StopTime = MPI_Wtime();
18082 #endif
18083  UsedTime = StopTime-StartTime;
18084 
18085  /*--- Communicate the total file size for the restart ---*/
18086 
18087 #ifdef HAVE_MPI
18088  su2double my_file_size = file_size;
18089  SU2_MPI::Allreduce(&my_file_size, &file_size, 1,
18091 #endif
18092 
18093  /*--- Compute and store the bandwidth ---*/
18094 
18095  Bandwidth = file_size/(1.0e6)/UsedTime;
18096  config->SetRestart_Bandwidth_Agg(config->GetRestart_Bandwidth_Agg()+Bandwidth);
18097 
18098  if ((rank == MASTER_NODE) && (wrt_perf)) {
18099  cout << "Wrote " << file_size/1.0e6 << " MB to disk in ";
18100  cout << UsedTime << " s. (" << Bandwidth << " MB/s)." << endl;
18101  }
18102 
18103  /*--- Free temporary data buffer for writing the binary file. ---*/
18104 
18105  delete [] buf;
18106 
18107 }
18108 
18110  CSolver *FlowSolver, unsigned long iExtIter,
18111  unsigned short val_iZone, unsigned short val_direction) {
18112 
18113  /*--- This routine is for exporting slices of field data for 2D cartesian
18114  grids. It assumes that the grid points lie on lines of constant x-
18115  or y-coordinates. It is a simple way to export slices or profiles on
18116  these meshes for use in verification and validation work. It will
18117  eventually be replaced by general routines for probing/slicing. ---*/
18118 
18119  int DIRECTION = (int)val_direction;
18120 
18121  su2double coordMin, coordMax;
18122  coordMin = config->GetStations_Bounds(0);
18123  coordMax = config->GetStations_Bounds(1);
18124 
18125  unsigned short iVar;
18126  unsigned long iPoint, iVertex, Global_Index;
18127  char cstr[200];
18128 
18129  int rank = MASTER_NODE, iProcessor, nProcessor = SINGLE_NODE;
18130 #ifdef HAVE_MPI
18131  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
18132  MPI_Comm_size(MPI_COMM_WORLD, &nProcessor);
18133 #endif
18134 
18135  bool isPeriodic;
18136 
18137  int *Local_Halo = new int[geometry->GetnPoint()];
18138  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
18139  Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain();
18140 
18141  for (unsigned short iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
18142  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
18143 
18144  /*--- Checking for less than or equal to the rank, because there may
18145  be some periodic halo nodes that send info to the same rank. ---*/
18146 
18147  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
18148  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
18149  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
18150  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1));
18151  if (isPeriodic) Local_Halo[iPoint] = false;
18152  }
18153  }
18154  }
18155 
18156  /*--- Sum total number of nodes that belong to the domain ---*/
18157 
18158  unsigned long nTotalPoint;
18159  unsigned long nLocalPoint = 0;
18160  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
18161  if (Local_Halo[iPoint] == false)
18162  nLocalPoint++;
18163 
18164 #ifdef HAVE_MPI
18165  SU2_MPI::Allreduce(&nLocalPoint, &nTotalPoint, 1,
18167 #else
18168  nTotalPoint = nLocalPoint;
18169 #endif
18170 
18171  unsigned long *npoint_procs = new unsigned long[nProcessor];
18172  unsigned long *nPoint_Linear = new unsigned long[nProcessor+1];
18173 
18174  unsigned long total_pt_accounted = 0;
18175  for (int ii = 0; ii < nProcessor; ii++) {
18176  npoint_procs[ii] = nTotalPoint/nProcessor;
18177  total_pt_accounted = total_pt_accounted + npoint_procs[ii];
18178  }
18179 
18180  /*--- Get the number of remainder points after the even division. ---*/
18181 
18182  unsigned long rem_points = nTotalPoint-total_pt_accounted;
18183  for (unsigned long ii = 0; ii < rem_points; ii++) {
18184  npoint_procs[ii]++;
18185  }
18186 
18187  /*--- Store the point offsets for each rank. ---*/
18188 
18189  nPoint_Linear[0] = 0;
18190  for (int ii = 1; ii < nProcessor; ii++) {
18191  nPoint_Linear[ii] = nPoint_Linear[ii-1] + npoint_procs[ii-1];
18192  }
18193  nPoint_Linear[nProcessor] = nTotalPoint;
18194 
18195  unsigned long Buffer_Send_nVertex[1], *Buffer_Recv_nVertex = NULL;
18196  unsigned long nLocalVertex_Surface = 0;
18197  unsigned long MaxLocalVertex_Surface = 0;
18198 
18199  /*--- Find the max number of vertices we will send from among all
18200  partitions and set up buffers. The master node will handle the
18201  writing of the CSV file after gathering all of the data. ---*/
18202 
18203  nLocalVertex_Surface = 0;
18204  for (iPoint = 0; iPoint < nParallel_Poin; iPoint++) {
18205 
18206  /*--- Global Index of the current point. (note outer loop over procs) ---*/
18207 
18208  Global_Index = iPoint + nPoint_Linear[rank];
18209 
18210  /*--- Only write original domain points, i.e., exclude any periodic
18211  or halo nodes, even if they are output in the viz. files. ---*/
18212 
18213  if (Global_Index < geometry->GetGlobal_nPointDomain()) {
18214  if ((Parallel_Data[DIRECTION][iPoint] > coordMin) &&
18215  (Parallel_Data[DIRECTION][iPoint] < coordMax)) {
18216  nLocalVertex_Surface++;
18217  }
18218  }
18219  }
18220 
18221  /*--- Communicate the number of local vertices on each partition
18222  to the master node ---*/
18223 
18224  Buffer_Send_nVertex[0] = nLocalVertex_Surface;
18225  if (rank == MASTER_NODE) Buffer_Recv_nVertex = new unsigned long [nProcessor];
18226 
18227 #ifdef HAVE_MPI
18228  SU2_MPI::Allreduce(&nLocalVertex_Surface, &MaxLocalVertex_Surface, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
18229  SU2_MPI::Gather(&Buffer_Send_nVertex, 1, MPI_UNSIGNED_LONG, Buffer_Recv_nVertex, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
18230 #else
18231  MaxLocalVertex_Surface = nLocalVertex_Surface;
18232  Buffer_Recv_nVertex[0] = Buffer_Send_nVertex[0];
18233 #endif
18234 
18235  /*--- Send and Recv buffers ---*/
18236 
18237  su2double *Buffer_Send_Data = new su2double [MaxLocalVertex_Surface*nVar_Par];
18238  su2double *Buffer_Recv_Data = NULL;
18239 
18240  unsigned long *Buffer_Send_GlobalIndex = new unsigned long [MaxLocalVertex_Surface];
18241  unsigned long *Buffer_Recv_GlobalIndex = NULL;
18242 
18243  /*--- Prepare the receive buffers on the master node only. ---*/
18244 
18245  if (rank == MASTER_NODE) {
18246  Buffer_Recv_Data = new su2double [nProcessor*MaxLocalVertex_Surface*nVar_Par];
18247  Buffer_Recv_GlobalIndex = new unsigned long [nProcessor*MaxLocalVertex_Surface];
18248  }
18249 
18250  /*--- Loop over all vertices in this partition and load the
18251  data of the specified type into the buffer to be sent to
18252  the master node. ---*/
18253 
18254  nLocalVertex_Surface = 0;
18255  for (iPoint = 0; iPoint < nParallel_Poin; iPoint++) {
18256 
18257  /*--- Global Index of the current point. (note outer loop over procs) ---*/
18258 
18259  Global_Index = iPoint + nPoint_Linear[rank];
18260 
18261  /*--- Only write original domain points, i.e., exclude any periodic
18262  or halo nodes, even if they are output in the viz. files. ---*/
18263 
18264  if (Global_Index < geometry->GetGlobal_nPointDomain()) {
18265  if ((Parallel_Data[DIRECTION][iPoint] > coordMin) &&
18266  (Parallel_Data[DIRECTION][iPoint] < coordMax)) {
18267  Buffer_Send_GlobalIndex[nLocalVertex_Surface] = Global_Index;
18268  for (iVar = 0; iVar < nVar_Par; iVar++) {
18269  Buffer_Send_Data[nLocalVertex_Surface*nVar_Par+iVar] = Parallel_Data[iVar][iPoint];
18270  }
18271  nLocalVertex_Surface++;
18272  }
18273  }
18274  }
18275 
18276  /*--- Send the information to the master node ---*/
18277 
18278 #ifdef HAVE_MPI
18279  SU2_MPI::Gather(Buffer_Send_Data, MaxLocalVertex_Surface*nVar_Par, MPI_DOUBLE, Buffer_Recv_Data, MaxLocalVertex_Surface*nVar_Par, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
18280  SU2_MPI::Gather(Buffer_Send_GlobalIndex, MaxLocalVertex_Surface, MPI_UNSIGNED_LONG, Buffer_Recv_GlobalIndex, MaxLocalVertex_Surface, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
18281 #else
18282  for (iVertex = 0; iVertex < Buffer_Recv_nVertex[0]; iVertex++) {
18283  Buffer_Recv_GlobalIndex[iVertex] = Buffer_Send_GlobalIndex[iVertex];
18284  for (iVar = 0; iVar < nVar_Par; iVar++) {
18285  Buffer_Recv_Data[iVertex*nVar_Par+iVar] = Buffer_Send_Data[iVertex*nVar_Par+iVar];
18286  }
18287  }
18288 #endif
18289 
18290  /*--- The master node unpacks the data and writes the surface CSV file ---*/
18291 
18292  if (rank == MASTER_NODE) {
18293 
18294  /*--- Write file name with extension if unsteady ---*/
18295  char buffer[50];
18296  string filename = "slice";
18297  if (DIRECTION == 0) {
18298  SPRINTF (buffer, "_vert.csv");
18299  } else if (DIRECTION == 1) {
18300  SPRINTF (buffer, "_hori.csv");
18301  }
18302  ofstream SurfFlow_file;
18303 
18304  /*--- Write file name with extension if unsteady ---*/
18305  strcpy (cstr, filename.c_str());
18306  strcat (cstr, buffer);
18307  SurfFlow_file.precision(15);
18308  SurfFlow_file.open(cstr, ios::out);
18309 
18310  /*--- Global index is first, then the rest of the data. We already have the names. ---*/
18311 
18312  SurfFlow_file << "\"Global_Index\",";
18313  for (iVar = 0; iVar < Variable_Names.size()-1; iVar++) {
18314  SurfFlow_file << "\"" << Variable_Names[iVar] << "\",";
18315  }
18316  SurfFlow_file << "\"" << Variable_Names[Variable_Names.size()-1] << "\"" << endl;
18317 
18318  /*--- Loop through all of the collected data and write each node's values ---*/
18319 
18320  unsigned long Total_Index;
18321  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
18322  for (iVertex = 0; iVertex < Buffer_Recv_nVertex[iProcessor]; iVertex++) {
18323 
18324  /*--- Current index position and global index ---*/
18325 
18326  Total_Index = iProcessor*MaxLocalVertex_Surface+iVertex;
18327  Global_Index = Buffer_Recv_GlobalIndex[Total_Index];
18328 
18329  /*--- Write the the data ---*/
18330 
18331  SurfFlow_file << scientific << Global_Index;
18332  Total_Index = iProcessor*MaxLocalVertex_Surface*nVar_Par+iVertex*nVar_Par;
18333  for (iVar = 0; iVar < nVar_Par; iVar++) {
18334  SurfFlow_file << scientific << ", " << Buffer_Recv_Data[Total_Index+iVar];
18335  }
18336  SurfFlow_file << endl;
18337 
18338  }
18339  }
18340 
18341  /*--- Close the CSV file ---*/
18342 
18343  SurfFlow_file.close();
18344 
18345  /*--- Release the recv buffers on the master node ---*/
18346 
18347  delete [] Buffer_Recv_Data;
18348  delete [] Buffer_Recv_GlobalIndex;
18349  delete [] Buffer_Recv_nVertex;
18350 
18351  }
18352 
18353  /*--- Release the memory for the remaining buffers and exit ---*/
18354 
18355  delete [] Buffer_Send_Data;
18356  delete [] Buffer_Send_GlobalIndex;
18357 
18358 }
18359 
18360 void COutputLegacy::DeallocateConnectivity_Parallel(CConfig *config, CGeometry *geometry, bool surf_sol) {
18361 
18362  /*--- Deallocate memory for connectivity data on each processor. ---*/
18363 
18364  if (surf_sol) {
18365  if (Conn_BoundLine_Par != NULL) delete [] Conn_BoundLine_Par;
18366  if (Conn_BoundTria_Par != NULL) delete [] Conn_BoundTria_Par;
18367  if (Conn_BoundQuad_Par != NULL) delete [] Conn_BoundQuad_Par;
18368  }
18369  else {
18370  if (Conn_Tria_Par != NULL) delete [] Conn_Tria_Par;
18371  if (Conn_Quad_Par != NULL) delete [] Conn_Quad_Par;
18372  if (Conn_Tetr_Par != NULL) delete [] Conn_Tetr_Par;
18373  if (Conn_Hexa_Par != NULL) delete [] Conn_Hexa_Par;
18374  if (Conn_Pris_Par != NULL) delete [] Conn_Pris_Par;
18375  if (Conn_Pyra_Par != NULL) delete [] Conn_Pyra_Par;
18376  }
18377 
18378 }
18379 
18381 
18382  /*--- Deallocate memory for solution data ---*/
18383 
18384  for (unsigned short iVar = 0; iVar < nVar_Par; iVar++) {
18385  if (Parallel_Data[iVar] != NULL) delete [] Parallel_Data[iVar];
18386  }
18387  if (Parallel_Data != NULL) delete [] Parallel_Data;
18388 
18389  /*--- Deallocate the structures holding the linear partitioning ---*/
18390 
18391  if (Local_Halo_Sort != NULL) delete [] Local_Halo_Sort;
18392 
18393  if (beg_node != NULL) delete [] beg_node;
18394  if (end_node != NULL) delete [] end_node;
18395 
18396  if (nPointLinear != NULL) delete [] nPointLinear;
18397  if (nPointCumulative != NULL) delete [] nPointCumulative;
18398 
18399 }
18400 
18402 
18403  /*--- Deallocate memory for surface solution data ---*/
18404 
18405  for (unsigned short iVar = 0; iVar < nVar_Par; iVar++) {
18406  if (Parallel_Surf_Data[iVar] != NULL) delete [] Parallel_Surf_Data[iVar];
18407  }
18408  if (Parallel_Surf_Data != NULL) delete [] Parallel_Surf_Data;
18409 
18410 }
18411 
18412 void COutputLegacy::SpecialOutput_AnalyzeSurface(CSolver *solver, CGeometry *geometry, CConfig *config, bool output) {
18413 
18414  unsigned short iDim, iMarker, iMarker_Analyze;
18415  unsigned long iVertex, iPoint;
18416  su2double Mach = 0.0, Pressure, Temperature = 0.0, TotalPressure = 0.0, TotalTemperature = 0.0,
18417  Enthalpy, Velocity[3], TangVel[3], Velocity2, MassFlow, Density, Area,
18418  AxiFactor = 1.0, SoundSpeed, Vn, Vn2, Vtang2, Weight = 1.0;
18419 
18420  su2double Gas_Constant = config->GetGas_ConstantND();
18421  su2double Gamma = config->GetGamma();
18422  unsigned short nMarker = config->GetnMarker_All();
18423  unsigned short nDim = geometry->GetnDim();
18424  unsigned short Kind_Average = config->GetKind_Average();
18425 
18426  bool compressible = config->GetKind_Regime() == COMPRESSIBLE;
18427  bool incompressible = config->GetKind_Regime() == INCOMPRESSIBLE;
18428  bool energy = config->GetEnergy_Equation();
18429 
18430 
18431  bool axisymmetric = config->GetAxisymmetric();
18432  unsigned short nMarker_Analyze = config->GetnMarker_Analyze();
18433 
18434  su2double *Vector = new su2double[nDim];
18435  su2double *Surface_MassFlow = new su2double[nMarker];
18436  su2double *Surface_Mach = new su2double[nMarker];
18437  su2double *Surface_Temperature = new su2double[nMarker];
18438  su2double *Surface_Density = new su2double[nMarker];
18439  su2double *Surface_Enthalpy = new su2double[nMarker];
18440  su2double *Surface_NormalVelocity = new su2double[nMarker];
18441  su2double *Surface_StreamVelocity2 = new su2double[nMarker];
18442  su2double *Surface_TransvVelocity2 = new su2double[nMarker];
18443  su2double *Surface_Pressure = new su2double[nMarker];
18444  su2double *Surface_TotalTemperature = new su2double[nMarker];
18445  su2double *Surface_TotalPressure = new su2double[nMarker];
18446  su2double *Surface_VelocityIdeal = new su2double[nMarker];
18447  su2double *Surface_Area = new su2double[nMarker];
18448  su2double *Surface_MassFlow_Abs = new su2double[nMarker];
18449 
18450  /*--- Compute the numerical fan face Mach number, and the total area of the inflow ---*/
18451 
18452  for (iMarker = 0; iMarker < nMarker; iMarker++) {
18453 
18454  Surface_MassFlow[iMarker] = 0.0;
18455  Surface_Mach[iMarker] = 0.0;
18456  Surface_Temperature[iMarker] = 0.0;
18457  Surface_Density[iMarker] = 0.0;
18458  Surface_Enthalpy[iMarker] = 0.0;
18459  Surface_NormalVelocity[iMarker] = 0.0;
18460  Surface_StreamVelocity2[iMarker] = 0.0;
18461  Surface_TransvVelocity2[iMarker] = 0.0;
18462  Surface_Pressure[iMarker] = 0.0;
18463  Surface_TotalTemperature[iMarker] = 0.0;
18464  Surface_TotalPressure[iMarker] = 0.0;
18465  Surface_VelocityIdeal[iMarker] = 0.0;
18466  Surface_Area[iMarker] = 0.0;
18467  Surface_MassFlow_Abs[iMarker] = 0.0;
18468 
18469  if (config->GetMarker_All_Analyze(iMarker) == YES) {
18470 
18471  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
18472  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
18473 
18474  if (geometry->node[iPoint]->GetDomain()) {
18475 
18476  geometry->vertex[iMarker][iVertex]->GetNormal(Vector);
18477 
18478  if (axisymmetric) {
18479  if (geometry->node[iPoint]->GetCoord(1) != 0.0)
18480  AxiFactor = 2.0*PI_NUMBER*geometry->node[iPoint]->GetCoord(1);
18481  else
18482  AxiFactor = 1.0;
18483  } else {
18484  AxiFactor = 1.0;
18485  }
18486 
18487  Density = solver->GetNodes()->GetDensity(iPoint);
18488  Velocity2 = 0.0; Area = 0.0; MassFlow = 0.0; Vn = 0.0; Vtang2 = 0.0;
18489 
18490  for (iDim = 0; iDim < nDim; iDim++) {
18491  Area += (Vector[iDim] * AxiFactor) * (Vector[iDim] * AxiFactor);
18492  Velocity[iDim] = solver->GetNodes()->GetVelocity(iPoint,iDim);
18493  Velocity2 += Velocity[iDim] * Velocity[iDim];
18494  Vn += Velocity[iDim] * Vector[iDim] * AxiFactor;
18495  MassFlow += Vector[iDim] * AxiFactor * Density * Velocity[iDim];
18496  }
18497 
18498  Area = sqrt (Area);
18499  if (AxiFactor == 0.0) Vn = 0.0; else Vn /= Area;
18500  Vn2 = Vn * Vn;
18501  Pressure = solver->GetNodes()->GetPressure(iPoint);
18502  SoundSpeed = solver->GetNodes()->GetSoundSpeed(iPoint);
18503 
18504  for (iDim = 0; iDim < nDim; iDim++) {
18505  TangVel[iDim] = Velocity[iDim] - Vn*Vector[iDim]*AxiFactor/Area;
18506  Vtang2 += TangVel[iDim]*TangVel[iDim];
18507  }
18508 
18509  if (incompressible){
18510  if (config->GetKind_DensityModel() == VARIABLE) {
18511  Mach = sqrt(solver->GetNodes()->GetVelocity2(iPoint))/
18512  sqrt(solver->GetNodes()->GetSpecificHeatCp(iPoint)*config->GetPressure_ThermodynamicND()/(solver->GetNodes()->GetSpecificHeatCv(iPoint)*solver->GetNodes()->GetDensity(iPoint)));
18513  } else {
18514  Mach = sqrt(solver->GetNodes()->GetVelocity2(iPoint))/
18515  sqrt(config->GetBulk_Modulus()/(solver->GetNodes()->GetDensity(iPoint)));
18516  }
18517  Temperature = solver->GetNodes()->GetTemperature(iPoint);
18518  Enthalpy = solver->GetNodes()->GetSpecificHeatCp(iPoint)*Temperature;
18519  TotalTemperature = Temperature + 0.5*Velocity2/solver->GetNodes()->GetSpecificHeatCp(iPoint);
18520  TotalPressure = Pressure + 0.5*Density*Velocity2;
18521  }
18522  else{
18523  Mach = sqrt(Velocity2)/SoundSpeed;
18524  Temperature = Pressure / (Gas_Constant * Density);
18525  Enthalpy = solver->GetNodes()->GetEnthalpy(iPoint);
18526  TotalTemperature = Temperature * (1.0 + Mach * Mach * 0.5 * (Gamma - 1.0));
18527  TotalPressure = Pressure * pow( 1.0 + Mach * Mach * 0.5 * (Gamma - 1.0), Gamma / (Gamma - 1.0));
18528  }
18529 
18530  /*--- Compute the mass Surface_MassFlow ---*/
18531 
18532  Surface_Area[iMarker] += Area;
18533  Surface_MassFlow[iMarker] += MassFlow;
18534  Surface_MassFlow_Abs[iMarker] += abs(MassFlow);
18535 
18536  if (Kind_Average == AVERAGE_MASSFLUX) Weight = abs(MassFlow);
18537  else if (Kind_Average == AVERAGE_AREA) Weight = abs(Area);
18538  else Weight = 1.0;
18539 
18540  Surface_Mach[iMarker] += Mach*Weight;
18541  Surface_Temperature[iMarker] += Temperature*Weight;
18542  Surface_Density[iMarker] += Density*Weight;
18543  Surface_Enthalpy[iMarker] += Enthalpy*Weight;
18544  Surface_NormalVelocity[iMarker] += Vn*Weight;
18545  Surface_Pressure[iMarker] += Pressure*Weight;
18546  Surface_TotalTemperature[iMarker] += TotalTemperature*Weight;
18547  Surface_TotalPressure[iMarker] += TotalPressure*Weight;
18548 
18549  /*--- For now, always used the area to weight the uniformities. ---*/
18550 
18551  Weight = abs(Area);
18552 
18553  Surface_StreamVelocity2[iMarker] += Vn2*Weight;
18554  Surface_TransvVelocity2[iMarker] += Vtang2*Weight;
18555 
18556  }
18557  }
18558 
18559  }
18560 
18561  }
18562 
18563  /*--- Copy to the appropriate structure ---*/
18564 
18565  su2double *Surface_MassFlow_Local = new su2double [nMarker_Analyze];
18566  su2double *Surface_Mach_Local = new su2double [nMarker_Analyze];
18567  su2double *Surface_Temperature_Local = new su2double [nMarker_Analyze];
18568  su2double *Surface_Density_Local = new su2double [nMarker_Analyze];
18569  su2double *Surface_Enthalpy_Local = new su2double [nMarker_Analyze];
18570  su2double *Surface_NormalVelocity_Local = new su2double [nMarker_Analyze];
18571  su2double *Surface_StreamVelocity2_Local = new su2double [nMarker_Analyze];
18572  su2double *Surface_TransvVelocity2_Local = new su2double [nMarker_Analyze];
18573  su2double *Surface_Pressure_Local = new su2double [nMarker_Analyze];
18574  su2double *Surface_TotalTemperature_Local = new su2double [nMarker_Analyze];
18575  su2double *Surface_TotalPressure_Local = new su2double [nMarker_Analyze];
18576  su2double *Surface_Area_Local = new su2double [nMarker_Analyze];
18577  su2double *Surface_MassFlow_Abs_Local = new su2double [nMarker_Analyze];
18578 
18579  su2double *Surface_MassFlow_Total = new su2double [nMarker_Analyze];
18580  su2double *Surface_Mach_Total = new su2double [nMarker_Analyze];
18581  su2double *Surface_Temperature_Total = new su2double [nMarker_Analyze];
18582  su2double *Surface_Density_Total = new su2double [nMarker_Analyze];
18583  su2double *Surface_Enthalpy_Total = new su2double [nMarker_Analyze];
18584  su2double *Surface_NormalVelocity_Total = new su2double [nMarker_Analyze];
18585  su2double *Surface_StreamVelocity2_Total = new su2double [nMarker_Analyze];
18586  su2double *Surface_TransvVelocity2_Total = new su2double [nMarker_Analyze];
18587  su2double *Surface_Pressure_Total = new su2double [nMarker_Analyze];
18588  su2double *Surface_TotalTemperature_Total = new su2double [nMarker_Analyze];
18589  su2double *Surface_TotalPressure_Total = new su2double [nMarker_Analyze];
18590  su2double *Surface_Area_Total = new su2double [nMarker_Analyze];
18591  su2double *Surface_MassFlow_Abs_Total = new su2double [nMarker_Analyze];
18592 
18593  su2double *Surface_MomentumDistortion_Total = new su2double [nMarker_Analyze];
18594 
18595  for (iMarker_Analyze = 0; iMarker_Analyze < nMarker_Analyze; iMarker_Analyze++) {
18596  Surface_MassFlow_Local[iMarker_Analyze] = 0.0;
18597  Surface_Mach_Local[iMarker_Analyze] = 0.0;
18598  Surface_Temperature_Local[iMarker_Analyze] = 0.0;
18599  Surface_Density_Local[iMarker_Analyze] = 0.0;
18600  Surface_Enthalpy_Local[iMarker_Analyze] = 0.0;
18601  Surface_NormalVelocity_Local[iMarker_Analyze] = 0.0;
18602  Surface_StreamVelocity2_Local[iMarker_Analyze] = 0.0;
18603  Surface_TransvVelocity2_Local[iMarker_Analyze] = 0.0;
18604  Surface_Pressure_Local[iMarker_Analyze] = 0.0;
18605  Surface_TotalTemperature_Local[iMarker_Analyze] = 0.0;
18606  Surface_TotalPressure_Local[iMarker_Analyze] = 0.0;
18607  Surface_Area_Local[iMarker_Analyze] = 0.0;
18608  Surface_MassFlow_Abs_Local[iMarker_Analyze] = 0.0;
18609 
18610  Surface_MassFlow_Total[iMarker_Analyze] = 0.0;
18611  Surface_Mach_Total[iMarker_Analyze] = 0.0;
18612  Surface_Temperature_Total[iMarker_Analyze] = 0.0;
18613  Surface_Density_Total[iMarker_Analyze] = 0.0;
18614  Surface_Enthalpy_Total[iMarker_Analyze] = 0.0;
18615  Surface_NormalVelocity_Total[iMarker_Analyze] = 0.0;
18616  Surface_StreamVelocity2_Total[iMarker_Analyze] = 0.0;
18617  Surface_TransvVelocity2_Total[iMarker_Analyze] = 0.0;
18618  Surface_Pressure_Total[iMarker_Analyze] = 0.0;
18619  Surface_TotalTemperature_Total[iMarker_Analyze] = 0.0;
18620  Surface_TotalPressure_Total[iMarker_Analyze] = 0.0;
18621  Surface_Area_Total[iMarker_Analyze] = 0.0;
18622  Surface_MassFlow_Abs_Total[iMarker_Analyze] = 0.0;
18623 
18624  Surface_MomentumDistortion_Total[iMarker_Analyze] = 0.0;
18625 
18626  }
18627 
18628  /*--- Compute the numerical fan face Mach number, mach number, temperature and the total area ---*/
18629 
18630  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
18631 
18632  if (config->GetMarker_All_Analyze(iMarker) == YES) {
18633 
18634  for (iMarker_Analyze= 0; iMarker_Analyze < nMarker_Analyze; iMarker_Analyze++) {
18635 
18636  /*--- Add the Surface_MassFlow, and Surface_Area to the particular boundary ---*/
18637 
18638  if (config->GetMarker_All_TagBound(iMarker) == config->GetMarker_Analyze_TagBound(iMarker_Analyze)) {
18639  Surface_MassFlow_Local[iMarker_Analyze] += Surface_MassFlow[iMarker];
18640  Surface_Mach_Local[iMarker_Analyze] += Surface_Mach[iMarker];
18641  Surface_Temperature_Local[iMarker_Analyze] += Surface_Temperature[iMarker];
18642  Surface_Density_Local[iMarker_Analyze] += Surface_Density[iMarker];
18643  Surface_Enthalpy_Local[iMarker_Analyze] += Surface_Enthalpy[iMarker];
18644  Surface_NormalVelocity_Local[iMarker_Analyze] += Surface_NormalVelocity[iMarker];
18645  Surface_StreamVelocity2_Local[iMarker_Analyze] += Surface_StreamVelocity2[iMarker];
18646  Surface_TransvVelocity2_Local[iMarker_Analyze] += Surface_TransvVelocity2[iMarker];
18647  Surface_Pressure_Local[iMarker_Analyze] += Surface_Pressure[iMarker];
18648  Surface_TotalTemperature_Local[iMarker_Analyze] += Surface_TotalTemperature[iMarker];
18649  Surface_TotalPressure_Local[iMarker_Analyze] += Surface_TotalPressure[iMarker];
18650  Surface_Area_Local[iMarker_Analyze] += Surface_Area[iMarker];
18651  Surface_MassFlow_Abs_Local[iMarker_Analyze] += Surface_MassFlow_Abs[iMarker];
18652  }
18653 
18654  }
18655 
18656  }
18657 
18658  }
18659 
18660 #ifdef HAVE_MPI
18661  if (config->GetComm_Level() == COMM_FULL) {
18662  SU2_MPI::Allreduce(Surface_MassFlow_Local, Surface_MassFlow_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
18663  SU2_MPI::Allreduce(Surface_Mach_Local, Surface_Mach_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
18664  SU2_MPI::Allreduce(Surface_Temperature_Local, Surface_Temperature_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
18665  SU2_MPI::Allreduce(Surface_Density_Local, Surface_Density_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
18666  SU2_MPI::Allreduce(Surface_Enthalpy_Local, Surface_Enthalpy_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
18667  SU2_MPI::Allreduce(Surface_NormalVelocity_Local, Surface_NormalVelocity_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
18668  SU2_MPI::Allreduce(Surface_StreamVelocity2_Local, Surface_StreamVelocity2_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
18669  SU2_MPI::Allreduce(Surface_TransvVelocity2_Local, Surface_TransvVelocity2_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
18670  SU2_MPI::Allreduce(Surface_Pressure_Local, Surface_Pressure_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
18671  SU2_MPI::Allreduce(Surface_TotalTemperature_Local, Surface_TotalTemperature_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
18672  SU2_MPI::Allreduce(Surface_TotalPressure_Local, Surface_TotalPressure_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
18673  SU2_MPI::Allreduce(Surface_Area_Local, Surface_Area_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
18674  SU2_MPI::Allreduce(Surface_MassFlow_Abs_Local, Surface_MassFlow_Abs_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
18675  }
18676 #else
18677 
18678  for (iMarker_Analyze = 0; iMarker_Analyze < nMarker_Analyze; iMarker_Analyze++) {
18679  Surface_MassFlow_Total[iMarker_Analyze] = Surface_MassFlow_Local[iMarker_Analyze];
18680  Surface_Mach_Total[iMarker_Analyze] = Surface_Mach_Local[iMarker_Analyze];
18681  Surface_Temperature_Total[iMarker_Analyze] = Surface_Temperature_Local[iMarker_Analyze];
18682  Surface_Density_Total[iMarker_Analyze] = Surface_Density_Local[iMarker_Analyze];
18683  Surface_Enthalpy_Total[iMarker_Analyze] = Surface_Enthalpy_Local[iMarker_Analyze];
18684  Surface_NormalVelocity_Total[iMarker_Analyze] = Surface_NormalVelocity_Local[iMarker_Analyze];
18685  Surface_StreamVelocity2_Total[iMarker_Analyze] = Surface_StreamVelocity2_Local[iMarker_Analyze];
18686  Surface_TransvVelocity2_Total[iMarker_Analyze] = Surface_TransvVelocity2_Local[iMarker_Analyze];
18687  Surface_Pressure_Total[iMarker_Analyze] = Surface_Pressure_Local[iMarker_Analyze];
18688  Surface_TotalTemperature_Total[iMarker_Analyze] = Surface_TotalTemperature_Local[iMarker_Analyze];
18689  Surface_TotalPressure_Total[iMarker_Analyze] = Surface_TotalPressure_Local[iMarker_Analyze];
18690  Surface_Area_Total[iMarker_Analyze] = Surface_Area_Local[iMarker_Analyze];
18691  Surface_MassFlow_Abs_Total[iMarker_Analyze] = Surface_MassFlow_Abs_Local[iMarker_Analyze];
18692  }
18693 
18694 #endif
18695 
18696  /*--- Compute the value of Surface_Area_Total, and Surface_Pressure_Total, and
18697  set the value in the config structure for future use ---*/
18698 
18699  for (iMarker_Analyze = 0; iMarker_Analyze < nMarker_Analyze; iMarker_Analyze++) {
18700 
18701  if (Kind_Average == AVERAGE_MASSFLUX) Weight = Surface_MassFlow_Abs_Total[iMarker_Analyze];
18702  else if (Kind_Average == AVERAGE_AREA) Weight = abs(Surface_Area_Total[iMarker_Analyze]);
18703  else Weight = 1.0;
18704 
18705  if (Weight != 0.0) {
18706  Surface_Mach_Total[iMarker_Analyze] /= Weight;
18707  Surface_Temperature_Total[iMarker_Analyze] /= Weight;
18708  Surface_Density_Total[iMarker_Analyze] /= Weight;
18709  Surface_Enthalpy_Total[iMarker_Analyze] /= Weight;
18710  Surface_NormalVelocity_Total[iMarker_Analyze] /= Weight;
18711  Surface_Pressure_Total[iMarker_Analyze] /= Weight;
18712  Surface_TotalTemperature_Total[iMarker_Analyze] /= Weight;
18713  Surface_TotalPressure_Total[iMarker_Analyze] /= Weight;
18714  }
18715  else {
18716  Surface_Mach_Total[iMarker_Analyze] = 0.0;
18717  Surface_Temperature_Total[iMarker_Analyze] = 0.0;
18718  Surface_Density_Total[iMarker_Analyze] = 0.0;
18719  Surface_Enthalpy_Total[iMarker_Analyze] = 0.0;
18720  Surface_NormalVelocity_Total[iMarker_Analyze] = 0.0;
18721  Surface_Pressure_Total[iMarker_Analyze] = 0.0;
18722  Surface_TotalTemperature_Total[iMarker_Analyze] = 0.0;
18723  Surface_TotalPressure_Total[iMarker_Analyze] = 0.0;
18724  }
18725 
18726  /*--- Compute flow uniformity parameters separately (always area for now). ---*/
18727 
18728  Area = fabs(Surface_Area_Total[iMarker_Analyze]);
18729 
18730  if (Area != 0.0) {
18731  Surface_MomentumDistortion_Total[iMarker_Analyze] = Surface_StreamVelocity2_Total[iMarker_Analyze]/(Surface_NormalVelocity_Total[iMarker_Analyze]*Surface_NormalVelocity_Total[iMarker_Analyze]*Area) - 1.0;
18732  Surface_StreamVelocity2_Total[iMarker_Analyze] /= Area;
18733  Surface_TransvVelocity2_Total[iMarker_Analyze] /= Area;
18734  }
18735  else {
18736  Surface_MomentumDistortion_Total[iMarker_Analyze] = 0.0;
18737  Surface_StreamVelocity2_Total[iMarker_Analyze] = 0.0;
18738  Surface_TransvVelocity2_Total[iMarker_Analyze] = 0.0;
18739  }
18740 
18741  }
18742 
18743  for (iMarker_Analyze = 0; iMarker_Analyze < nMarker_Analyze; iMarker_Analyze++) {
18744 
18745  su2double MassFlow = Surface_MassFlow_Total[iMarker_Analyze] * config->GetDensity_Ref() * config->GetVelocity_Ref();
18746  if (config->GetSystemMeasurements() == US) MassFlow *= 32.174;
18747  config->SetSurface_MassFlow(iMarker_Analyze, MassFlow);
18748 
18749  su2double Mach = Surface_Mach_Total[iMarker_Analyze];
18750  config->SetSurface_Mach(iMarker_Analyze, Mach);
18751 
18752  su2double Temperature = Surface_Temperature_Total[iMarker_Analyze] * config->GetTemperature_Ref();
18753  config->SetSurface_Temperature(iMarker_Analyze, Temperature);
18754 
18755  su2double Pressure = Surface_Pressure_Total[iMarker_Analyze] * config->GetPressure_Ref();
18756  config->SetSurface_Pressure(iMarker_Analyze, Pressure);
18757 
18758  su2double Density = Surface_Density_Total[iMarker_Analyze] * config->GetDensity_Ref();
18759  config->SetSurface_Density(iMarker_Analyze, Density);
18760 
18761  su2double Enthalpy = Surface_Enthalpy_Total[iMarker_Analyze];
18762  config->SetSurface_Enthalpy(iMarker_Analyze, Enthalpy);
18763 
18764  su2double NormalVelocity = Surface_NormalVelocity_Total[iMarker_Analyze] * config->GetVelocity_Ref();
18765  config->SetSurface_NormalVelocity(iMarker_Analyze, NormalVelocity);
18766 
18767  su2double Uniformity = sqrt(Surface_StreamVelocity2_Total[iMarker_Analyze]) * config->GetVelocity_Ref();
18768  config->SetSurface_Uniformity(iMarker_Analyze, Uniformity);
18769 
18770  su2double SecondaryStrength = sqrt(Surface_TransvVelocity2_Total[iMarker_Analyze]) * config->GetVelocity_Ref();
18771  config->SetSurface_SecondaryStrength(iMarker_Analyze, SecondaryStrength);
18772 
18773  su2double MomentumDistortion = Surface_MomentumDistortion_Total[iMarker_Analyze];
18774  config->SetSurface_MomentumDistortion(iMarker_Analyze, MomentumDistortion);
18775 
18776  su2double SecondOverUniform = SecondaryStrength/Uniformity;
18777  config->SetSurface_SecondOverUniform(iMarker_Analyze, SecondOverUniform);
18778 
18779  su2double TotalTemperature = Surface_TotalTemperature_Total[iMarker_Analyze] * config->GetTemperature_Ref();
18780  config->SetSurface_TotalTemperature(iMarker_Analyze, TotalTemperature);
18781 
18782  su2double TotalPressure = Surface_TotalPressure_Total[iMarker_Analyze] * config->GetPressure_Ref();
18783  config->SetSurface_TotalPressure(iMarker_Analyze, TotalPressure);
18784 
18785  }
18786 
18787  /*--- Compute the average static pressure drop between two surfaces. Note
18788  that this assumes we have two surfaces being analyzed and that the outlet
18789  is first followed by the inlet. This is because we may also want to choose
18790  outlet values (temperature, uniformity, etc.) for our design problems,
18791  which require the outlet to be listed first. This is a simple first version
18792  that could be generalized to a different orders/lists/etc. ---*/
18793 
18794  for (iMarker_Analyze = 0; iMarker_Analyze < nMarker_Analyze; iMarker_Analyze++) {
18795  if (nMarker_Analyze == 2) {
18796  su2double Pressure_Drop = (Surface_Pressure_Total[1]-Surface_Pressure_Total[0]) * config->GetPressure_Ref();
18797  config->SetSurface_PressureDrop(iMarker_Analyze, Pressure_Drop);
18798  } else {
18799  config->SetSurface_PressureDrop(iMarker_Analyze, 0.0);
18800  }
18801  }
18802 
18803  if ((rank == MASTER_NODE) && !config->GetDiscrete_Adjoint() && output) {
18804 
18805  cout.precision(6);
18806  cout.setf(ios::scientific, ios::floatfield);
18807  cout << endl << "Computing surface mean values." << endl << endl;
18808 
18809  for (iMarker_Analyze = 0; iMarker_Analyze < nMarker_Analyze; iMarker_Analyze++) {
18810  cout << "Surface "<< config->GetMarker_Analyze_TagBound(iMarker_Analyze) << ":" << endl;
18811 
18812  if (nDim == 3) { if (config->GetSystemMeasurements() == SI) cout << setw(20) << "Area (m^2): "; else cout << setw(20) << "Area (ft^2): "; }
18813  else { if (config->GetSystemMeasurements() == SI) cout << setw(20) << "Area (m): "; else cout << setw(20) << "Area (ft): "; }
18814 
18815  if (config->GetSystemMeasurements() == SI) cout << setw(15) << fabs(Surface_Area_Total[iMarker_Analyze]);
18816  else if (config->GetSystemMeasurements() == US) cout << setw(15) << fabs(Surface_Area_Total[iMarker_Analyze])*12.0*12.0;
18817 
18818  cout << endl;
18819 
18820  su2double MassFlow = config->GetSurface_MassFlow(iMarker_Analyze);
18821  if (config->GetSystemMeasurements() == SI) cout << setw(20) << "Mf (kg/s): " << setw(15) << MassFlow;
18822  else if (config->GetSystemMeasurements() == US) cout << setw(20) << "Mf (lbs/s): " << setw(15) << MassFlow;
18823 
18824  su2double NormalVelocity = config->GetSurface_NormalVelocity(iMarker_Analyze);
18825  if (config->GetSystemMeasurements() == SI) cout << setw(20) << "Vn (m/s): " << setw(15) << NormalVelocity;
18826  else if (config->GetSystemMeasurements() == US) cout << setw(20) << "Vn (ft/s): " << setw(15) << NormalVelocity;
18827 
18828  cout << endl;
18829 
18830  su2double Uniformity = config->GetSurface_Uniformity(iMarker_Analyze);
18831  if (config->GetSystemMeasurements() == SI) cout << setw(20) << "Uniformity (m/s): " << setw(15) << Uniformity;
18832  else if (config->GetSystemMeasurements() == US) cout << setw(20) << "Uniformity (ft/s): " << setw(15) << Uniformity;
18833 
18834  su2double SecondaryStrength = config->GetSurface_SecondaryStrength(iMarker_Analyze);
18835  if (config->GetSystemMeasurements() == SI) cout << setw(20) << "Secondary (m/s): " << setw(15) << SecondaryStrength;
18836  else if (config->GetSystemMeasurements() == US) cout << setw(20) << "Secondary (ft/s): " << setw(15) << SecondaryStrength;
18837 
18838  cout << endl;
18839 
18840  su2double MomentumDistortion = config->GetSurface_MomentumDistortion(iMarker_Analyze);
18841  cout << setw(20) << "Mom. Distortion: " << setw(15) << MomentumDistortion;
18842 
18843  su2double SecondOverUniform = config->GetSurface_SecondOverUniform(iMarker_Analyze);
18844  cout << setw(20) << "Second/Uniform: " << setw(15) << SecondOverUniform;
18845 
18846  cout << endl;
18847 
18848  su2double Pressure = config->GetSurface_Pressure(iMarker_Analyze);
18849  if (config->GetSystemMeasurements() == SI) cout << setw(20) << "P (Pa): " << setw(15) << Pressure;
18850  else if (config->GetSystemMeasurements() == US) cout << setw(20) << "P (psf): " << setw(15) << Pressure;
18851 
18852  su2double TotalPressure = config->GetSurface_TotalPressure(iMarker_Analyze);
18853  if (config->GetSystemMeasurements() == SI) cout << setw(20) << "PT (Pa): " << setw(15) <<TotalPressure;
18854  else if (config->GetSystemMeasurements() == US) cout << setw(20) << "PT (psf): " << setw(15) <<TotalPressure;
18855 
18856  cout << endl;
18857 
18858  su2double Mach = config->GetSurface_Mach(iMarker_Analyze);
18859  cout << setw(20) << "Mach: " << setw(15) << Mach;
18860 
18861  su2double Density = config->GetSurface_Density(iMarker_Analyze);
18862  if (config->GetSystemMeasurements() == SI) cout << setw(20) << "Rho (kg/m^3): " << setw(15) << Density;
18863  else if (config->GetSystemMeasurements() == US) cout << setw(20) << "Rho (lb/ft^3): " << setw(15) << Density*32.174;
18864 
18865  cout << endl;
18866 
18867  if (compressible || energy) {
18868  su2double Temperature = config->GetSurface_Temperature(iMarker_Analyze);
18869  if (config->GetSystemMeasurements() == SI) cout << setw(20) << "T (K): " << setw(15) << Temperature;
18870  else if (config->GetSystemMeasurements() == US) cout << setw(20) << "T (R): " << setw(15) << Temperature;
18871 
18872  su2double TotalTemperature = config->GetSurface_TotalTemperature(iMarker_Analyze);
18873  if (config->GetSystemMeasurements() == SI) cout << setw(20) << "TT (K): " << setw(15) << TotalTemperature;
18874  else if (config->GetSystemMeasurements() == US) cout << setw(20) << "TT (R): " << setw(15) << TotalTemperature;
18875 
18876  cout << endl;
18877  }
18878 
18879  }
18880  cout.unsetf(ios_base::floatfield);
18881 
18882  }
18883 
18884  delete [] Surface_MassFlow_Local;
18885  delete [] Surface_Mach_Local;
18886  delete [] Surface_Temperature_Local;
18887  delete [] Surface_Density_Local;
18888  delete [] Surface_Enthalpy_Local;
18889  delete [] Surface_NormalVelocity_Local;
18890  delete [] Surface_Pressure_Local;
18891  delete [] Surface_TotalTemperature_Local;
18892  delete [] Surface_TotalPressure_Local;
18893  delete [] Surface_Area_Local;
18894  delete [] Surface_MassFlow_Abs_Local;
18895 
18896  delete [] Surface_MassFlow_Total;
18897  delete [] Surface_Mach_Total;
18898  delete [] Surface_Temperature_Total;
18899  delete [] Surface_Density_Total;
18900  delete [] Surface_Enthalpy_Total;
18901  delete [] Surface_NormalVelocity_Total;
18902  delete [] Surface_Pressure_Total;
18903  delete [] Surface_TotalTemperature_Total;
18904  delete [] Surface_TotalPressure_Total;
18905  delete [] Surface_Area_Total;
18906  delete [] Surface_MassFlow_Abs_Total;
18907 
18908  delete [] Surface_MassFlow;
18909  delete [] Surface_Mach;
18910  delete [] Surface_Temperature;
18911  delete [] Surface_Density;
18912  delete [] Surface_Enthalpy;
18913  delete [] Surface_NormalVelocity;
18914  delete [] Surface_Pressure;
18915  delete [] Surface_TotalTemperature;
18916  delete [] Surface_TotalPressure;
18917  delete [] Surface_Area;
18918  delete [] Vector;
18919  delete [] Surface_VelocityIdeal;
18920  delete [] Surface_MassFlow_Abs;
18921 
18922 }
18923 
18924 void COutputLegacy::MergeConnectivity_FEM(CConfig *config, CGeometry *geometry, unsigned short val_iZone) {
18925 
18926  /*--- Flags identifying the types of files to be written. ---*/
18927 
18928  bool Wrt_Vol = config->GetWrt_Vol_Sol();
18929  bool Wrt_Srf = config->GetWrt_Srf_Sol();
18930 
18931  /*--- Merge connectivity for each type of element (excluding halos). Note
18932  that we only need to merge the connectivity once, as it does not change
18933  during computation. Check whether the base file has been written. ---*/
18934 
18935  /*--- Merge volumetric grid. ---*/
18936 
18937  if (Wrt_Vol) {
18938 
18939  if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_Tria != 0))
18940  cout <<"Merging volumetric triangle grid connectivity." << endl;
18941  MergeVolumetricConnectivity_FEM(config, geometry, TRIANGLE );
18942 
18943  if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_Quad != 0))
18944  cout <<"Merging volumetric quadrilateral grid connectivity." << endl;
18945  MergeVolumetricConnectivity_FEM(config, geometry, QUADRILATERAL );
18946 
18947  if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_Tetr != 0))
18948  cout <<"Merging volumetric tetrahedron grid connectivity." << endl;
18949  MergeVolumetricConnectivity_FEM(config, geometry, TETRAHEDRON );
18950 
18951  if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_Hexa != 0))
18952  cout <<"Merging volumetric hexahedron grid connectivity." << endl;
18953  MergeVolumetricConnectivity_FEM(config, geometry, HEXAHEDRON );
18954 
18955  if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_Pris != 0))
18956  cout <<"Merging volumetric prism grid connectivity." << endl;
18957  MergeVolumetricConnectivity_FEM(config, geometry, PRISM );
18958 
18959  if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_Pyra != 0))
18960  cout <<"Merging volumetric pyramid grid connectivity." << endl;
18961  MergeVolumetricConnectivity_FEM(config, geometry, PYRAMID );
18962 
18963  }
18964 
18965  /*--- Merge surface grid. ---*/
18966 
18967  if (Wrt_Srf) {
18968 
18969  if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_Line != 0))
18970  cout <<"Merging surface line grid connectivity." << endl;
18971  MergeSurfaceConnectivity_FEM(config, geometry, LINE);
18972 
18973  if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_BoundTria != 0))
18974  cout <<"Merging surface triangle grid connectivity." << endl;
18975  MergeSurfaceConnectivity_FEM(config, geometry, TRIANGLE);
18976 
18977  if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_BoundQuad != 0))
18978  cout <<"Merging surface quadrilateral grid connectivity." << endl;
18979  MergeSurfaceConnectivity_FEM(config, geometry, QUADRILATERAL);
18980 
18981  }
18982 
18983  /*--- Update total number of volume elements after merge. ---*/
18984 
18985  nGlobal_Elem = nGlobal_Tria + nGlobal_Quad + nGlobal_Tetr +
18986  nGlobal_Hexa + nGlobal_Pyra + nGlobal_Pris;
18987 
18988  /*--- Update total number of surface elements after merge. ---*/
18989 
18990  nSurf_Elem = nGlobal_Line + nGlobal_BoundTria + nGlobal_BoundQuad;
18991 
18992 }
18993 
18995 
18996  /*--- Local variables needed on all processors ---*/
18997 
18998  unsigned short iDim;
18999  unsigned long iPoint;
19000 
19001  /*--- Create an object of the class CMeshFEM_DG and retrieve the necessary
19002  geometrical information for the FEM DG solver. ---*/
19003  CMeshFEM_DG *DGGeometry = dynamic_cast<CMeshFEM_DG *>(geometry);
19004 
19005  unsigned short nDim = DGGeometry->GetnDim();
19006 
19007  unsigned long nVolElemOwned = DGGeometry->GetNVolElemOwned();
19008  CVolumeElementFEM *volElem = DGGeometry->GetVolElem();
19009 
19010  /*--- Create the map from the global DOF ID to the local index. ---*/
19011  vector<su2double> DOFsCoords;
19012  vector<unsigned long> globalID;
19013 
19014  /*--- Set the global ID and the coordinates of the local DOFs
19015  by looping over the owned volume elements. ---*/
19016  unsigned long nLocalPoint = 0;
19017  for(unsigned long l=0; l<nVolElemOwned; ++l) {
19018  for(unsigned short j=0; j<volElem[l].nDOFsSol; ++j) {
19019 
19020  const unsigned long globalIndex = volElem[l].offsetDOFsSolGlobal + j;
19021  globalID.push_back(globalIndex);
19022 
19023  const su2double *coor = volElem[l].coorSolDOFs.data() + j*nDim;
19024  for(unsigned short k=0; k<nDim; ++k) DOFsCoords.push_back(coor[k]);
19025 
19026  nLocalPoint++;
19027  }
19028  }
19029 
19030 #ifndef HAVE_MPI
19031 
19032  /*--- In serial, the single process has access to all geometry, so simply
19033  load the coordinates into the data structure. ---*/
19034 
19035  // need to double check for halos in parallel
19036 
19037  nGlobal_Poin = nLocalPoint;
19038  nGlobal_Doma = nLocalPoint;
19039 
19040  /*--- Allocate the coordinates data structure. ---*/
19041 
19042  Coords = new su2double*[nDim];
19043  for (iDim = 0; iDim < nDim; iDim++) {
19044  Coords[iDim] = new su2double[nGlobal_Poin];
19045  }
19046 
19047  /*--- Loop over the mesh to collect the coords of the local points ---*/
19048 
19049  for (iPoint = 0; iPoint < nLocalPoint; iPoint++) {
19050 
19051  /*--- Check if the node belongs to the domain (i.e, not a halo node).
19052  Sort by the global index, even in serial there is a renumbering (e.g. RCM). ---*/
19053 
19054  /*--- Retrieve the current coordinates at this node. ---*/
19055 
19056  unsigned long iGlobal_Index = globalID[iPoint];
19057 
19058  for (iDim = 0; iDim < nDim; iDim++) {
19059  Coords[iDim][iGlobal_Index] = DOFsCoords[iPoint*nDim+iDim];
19060 
19061  /*--- If US system, the output should be in inches ---*/
19062 
19063  if ((config->GetSystemMeasurements() == US) && (config->GetKind_SU2() != SU2_DEF)) {
19064  Coords[iDim][iGlobal_Index] *= 12.0;
19065  }
19066  }
19067  }
19068 
19069 #else
19070 
19071  /*--- MPI preprocessing ---*/
19072  int iProcessor, nProcessor = size;
19073  unsigned long jPoint;
19074 
19075  /*--- Local variables needed for merging the geometry with MPI. ---*/
19076 
19077  unsigned long Buffer_Send_nPoin[1], *Buffer_Recv_nPoin = NULL;
19078  unsigned long MaxLocalPoint = 0;
19079  unsigned long iGlobal_Index = 0, nBuffer_Scalar = 0;
19080 
19081  if (rank == MASTER_NODE) Buffer_Recv_nPoin = new unsigned long[nProcessor];
19082 
19083  /*--- Search all send/recv boundaries on this partition for any periodic
19084  nodes that were part of the original domain. We want to recover these
19085  for visualization purposes. ---*/
19086 
19087  // Need to double check halo layers
19088 
19089  Buffer_Send_nPoin[0] = nLocalPoint;
19090 
19091  /*--- Communicate the total number of nodes on this domain. ---*/
19092 
19093  SU2_MPI::Gather(&Buffer_Send_nPoin, 1, MPI_UNSIGNED_LONG,
19094  Buffer_Recv_nPoin, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
19095  SU2_MPI::Allreduce(&nLocalPoint, &MaxLocalPoint, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
19096 
19097  if (rank == MASTER_NODE) {
19098  nGlobal_Doma = 0;
19099  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
19100  nGlobal_Doma += Buffer_Recv_nPoin[iProcessor];
19101  }
19102  }
19103  nBuffer_Scalar = MaxLocalPoint;
19104 
19105  /*--- Send and Recv buffers. ---*/
19106 
19107  su2double *Buffer_Send_X = new su2double[MaxLocalPoint];
19108  su2double *Buffer_Recv_X = NULL;
19109 
19110  su2double *Buffer_Send_Y = new su2double[MaxLocalPoint];
19111  su2double *Buffer_Recv_Y = NULL;
19112 
19113  su2double *Buffer_Send_Z = NULL, *Buffer_Recv_Z = NULL;
19114  if (nDim == 3) Buffer_Send_Z = new su2double[MaxLocalPoint];
19115 
19116  unsigned long *Buffer_Send_GlobalIndex = new unsigned long[MaxLocalPoint];
19117  unsigned long *Buffer_Recv_GlobalIndex = NULL;
19118 
19119  /*--- Prepare the receive buffers in the master node only. ---*/
19120 
19121  if (rank == MASTER_NODE) {
19122 
19123  Buffer_Recv_X = new su2double[nProcessor*MaxLocalPoint];
19124  Buffer_Recv_Y = new su2double[nProcessor*MaxLocalPoint];
19125  if (nDim == 3) Buffer_Recv_Z = new su2double[nProcessor*MaxLocalPoint];
19126  Buffer_Recv_GlobalIndex = new unsigned long[nProcessor*MaxLocalPoint];
19127 
19128  /*--- Sum total number of nodes to be written and allocate arrays ---*/
19129  nGlobal_Poin = 0;
19130  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
19131  nGlobal_Poin += Buffer_Recv_nPoin[iProcessor];
19132  }
19133  Coords = new su2double*[nDim];
19134  for (iDim = 0; iDim < nDim; iDim++) {
19135  Coords[iDim] = new su2double[nGlobal_Poin];
19136  }
19137  }
19138 
19139  /*--- Main communication routine. Loop over each coordinate and perform
19140  the MPI comm. Temporary 1-D buffers are used to send the coordinates at
19141  all nodes on each partition to the master node. These are then unpacked
19142  by the master and sorted by global index in one large n-dim. array. ---*/
19143 
19144  /*--- Loop over this partition to collect the coords of the local points. ---*/
19145  jPoint = 0;
19146  for (iPoint = 0; iPoint < nLocalPoint; iPoint++) {
19147 
19148  /*--- Check for halos and write only if requested ---*/
19149  // if (!Local_Halo[iPoint] || Wrt_Halo) {
19150 
19151  /*--- Load local coords into the temporary send buffer. These were stored above ---*/
19152  Buffer_Send_X[jPoint] = DOFsCoords[iPoint*nDim+0];
19153  Buffer_Send_Y[jPoint] = DOFsCoords[iPoint*nDim+1];
19154  if (nDim == 3) Buffer_Send_Z[jPoint] = DOFsCoords[iPoint*nDim+2];
19155 
19156  /*--- If US system, the output should be in inches ---*/
19157 
19158  if ((config->GetSystemMeasurements() == US) && (config->GetKind_SU2() != SU2_DEF)) {
19159  Buffer_Send_X[jPoint] *= 12.0;
19160  Buffer_Send_Y[jPoint] *= 12.0;
19161  if (nDim == 3) Buffer_Send_Z[jPoint] *= 12.0;
19162  }
19163 
19164  /*--- Store the global index for this local node. ---*/
19165  Buffer_Send_GlobalIndex[jPoint] = globalID[iPoint];
19166 
19167  /*--- Increment jPoint as the counter. We need this because iPoint
19168  may include halo nodes that we skip over during this loop. ---*/
19169  jPoint++;
19170  // }
19171  }
19172 
19173  /*--- Gather the coordinate data on the master node using MPI. ---*/
19174 
19175  SU2_MPI::Gather(Buffer_Send_X, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_X, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
19176  SU2_MPI::Gather(Buffer_Send_Y, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Y, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
19177  if (nDim == 3) {
19178  SU2_MPI::Gather(Buffer_Send_Z, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Z, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
19179  }
19180  SU2_MPI::Gather(Buffer_Send_GlobalIndex, nBuffer_Scalar, MPI_UNSIGNED_LONG, Buffer_Recv_GlobalIndex, nBuffer_Scalar, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
19181 
19182  /*--- The master node unpacks and sorts this variable by global index ---*/
19183 
19184  if (rank == MASTER_NODE) {
19185  jPoint = 0;
19186  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
19187  for (iPoint = 0; iPoint < Buffer_Recv_nPoin[iProcessor]; iPoint++) {
19188  /*--- Get global index, then loop over each variable and store ---*/
19189  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
19190  if (iGlobal_Index >= nGlobal_Poin){
19191  cout << iGlobal_Index << " " << nGlobal_Poin << endl;
19192  }
19193  Coords[0][iGlobal_Index] = Buffer_Recv_X[jPoint];
19194  Coords[1][iGlobal_Index] = Buffer_Recv_Y[jPoint];
19195  if (nDim == 3) Coords[2][iGlobal_Index] = Buffer_Recv_Z[jPoint];
19196  jPoint++;
19197  }
19198  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
19199  jPoint = (iProcessor+1)*nBuffer_Scalar;
19200  }
19201  }
19202 
19203  /*--- Immediately release the temporary data buffers. ---*/
19204 
19205  // delete [] Local_Halo;
19206  delete [] Buffer_Send_X;
19207  delete [] Buffer_Send_Y;
19208  if (Buffer_Send_Z != NULL) delete [] Buffer_Send_Z;
19209  delete [] Buffer_Send_GlobalIndex;
19210  if (rank == MASTER_NODE) {
19211  delete [] Buffer_Recv_X;
19212  delete [] Buffer_Recv_Y;
19213  if (Buffer_Recv_Z != NULL) delete [] Buffer_Recv_Z;
19214  delete [] Buffer_Recv_GlobalIndex;
19215  delete [] Buffer_Recv_nPoin;
19216  }
19217 
19218 #endif
19219 
19220 }
19221 
19222 void COutputLegacy::MergeVolumetricConnectivity_FEM(CConfig *config, CGeometry *geometry, unsigned short Elem_Type) {
19223 
19224  int iProcessor;
19225  unsigned short NODES_PER_ELEMENT = 0;
19226  unsigned long iNode, jNode;
19227  unsigned long iElem = 0;
19228  unsigned long nLocalElem = 0, nElem_Total = 0;
19229 
19230  unsigned long jElem;
19231 
19232  unsigned long Buffer_Send_nElem[1], *Buffer_Recv_nElem = NULL;
19233  unsigned long nBuffer_Scalar = 0;
19234  unsigned long kNode = 0, kElem = 0;
19235  unsigned long MaxLocalElem = 0;
19236 
19237  bool Wrt_Halo = config->GetWrt_Halo();
19238  bool *Write_Elem = NULL;
19239 
19240  int *Conn_Elem = NULL;
19241 
19242  /*--- Create an object of the class CMeshFEM_DG and retrieve the necessary
19243  geometrical information for the FEM DG solver. ---*/
19244  CMeshFEM_DG *DGGeometry = dynamic_cast<CMeshFEM_DG *>(geometry);
19245 
19246  unsigned long nVolElemOwned = DGGeometry->GetNVolElemOwned();
19247 
19248  CVolumeElementFEM *volElem = DGGeometry->GetVolElem();
19249 
19250  const CFEMStandardElement *standardElementsSol = DGGeometry->GetStandardElementsSol();
19251 
19252  /* Define the vectors for the connectivity of the local linear subelements. */
19253  vector<unsigned long> volumeConn;
19254 
19255  /*--- Create the map from the global DOF ID to the local index. ---*/
19256  map<unsigned long, unsigned long> mapLocal2Global;
19257  unsigned long ii = 0;
19258  for(unsigned long i=0; i<nVolElemOwned; ++i) {
19259  for(unsigned short j=0; j<volElem[i].nDOFsSol; ++j, ++ii) {
19260  mapLocal2Global[ii] = volElem[i].offsetDOFsSolGlobal+j;
19261  }
19262  }
19263 
19264  /*--- Counter for keeping track of the number of this element locally. ---*/
19265  nLocalElem = 0;
19266  for(unsigned long i=0; i<nVolElemOwned; ++i) {
19267 
19268  /* Determine the necessary data from the corresponding standard elem,
19269  such as the number of linear sub elements, the number of DOFs per
19270  linear sub element and the corresponding local connectivity. */
19271  const unsigned short ind = volElem[i].indStandardElement;
19272  const unsigned short VTK_Type1 = standardElementsSol[ind].GetVTK_Type1();
19273  const unsigned short VTK_Type2 = standardElementsSol[ind].GetVTK_Type2();
19274 
19275  /*--- Only store the linear sub elements if they are of
19276  the current type that we are merging. ---*/
19277  if (Elem_Type == VTK_Type1) {
19278 
19279  const unsigned short nSubElems = standardElementsSol[ind].GetNSubElemsType1();
19280  const unsigned short nDOFsPerSubElem = standardElementsSol[ind].GetNDOFsPerSubElem(VTK_Type1);
19281  const unsigned short *connSubElems = standardElementsSol[ind].GetSubConnType1();
19282 
19283  /* Loop over the number of subfaces and store the required data. */
19284  unsigned short kk = 0;
19285  for(unsigned short j=0; j<nSubElems; ++j) {
19286 
19287  /*--- Store the global index for the surface conn ---*/
19288  for(unsigned short k=0; k<nDOFsPerSubElem; ++k, ++kk)
19289  volumeConn.push_back(mapLocal2Global[volElem[i].offsetDOFsSolLocal+connSubElems[kk]]);
19290 
19291  nLocalElem++;
19292  }
19293 
19294  } else if (Elem_Type == VTK_Type2) {
19295 
19296  const unsigned short nSubElems = standardElementsSol[ind].GetNSubElemsType2();
19297  const unsigned short nDOFsPerSubElem = standardElementsSol[ind].GetNDOFsPerSubElem(VTK_Type2);
19298  const unsigned short *connSubElems = standardElementsSol[ind].GetSubConnType2();
19299 
19300  /* Loop over the number of subfaces and store the required data. */
19301  unsigned short kk = 0;
19302  for(unsigned short j=0; j<nSubElems; ++j) {
19303 
19304  /*--- Store the global index for the surface conn ---*/
19305  for(unsigned short k=0; k<nDOFsPerSubElem; ++k, ++kk)
19306  volumeConn.push_back(mapLocal2Global[volElem[i].offsetDOFsSolLocal+connSubElems[kk]]);
19307 
19308  nLocalElem++;
19309  }
19310  }
19311  }
19312 
19313  /*--- Store the local number of this element type and the number of nodes
19314  per this element type. In serial, this will be the total number of this
19315  element type in the entire mesh. In parallel, it is the number on only
19316  the current partition. ---*/
19317 
19318  switch (Elem_Type) {
19319  case TRIANGLE:
19320  NODES_PER_ELEMENT = N_POINTS_TRIANGLE;
19321  break;
19322  case QUADRILATERAL:
19323  NODES_PER_ELEMENT = N_POINTS_QUADRILATERAL;
19324  break;
19325  case TETRAHEDRON:
19326  NODES_PER_ELEMENT = N_POINTS_TETRAHEDRON;
19327  break;
19328  case HEXAHEDRON:
19329  NODES_PER_ELEMENT = N_POINTS_HEXAHEDRON;
19330  break;
19331  case PRISM:
19332  NODES_PER_ELEMENT = N_POINTS_PRISM;
19333  break;
19334  case PYRAMID:
19335  NODES_PER_ELEMENT = N_POINTS_PYRAMID;
19336  break;
19337  default:
19338  SU2_MPI::Error("Unrecognized element type", CURRENT_FUNCTION);
19339  }
19340 
19341  /*--- Find the max number of this element type among all
19342  partitions and set up buffers. ---*/
19343 
19344  Buffer_Send_nElem[0] = nLocalElem;
19345  if (rank == MASTER_NODE) Buffer_Recv_nElem = new unsigned long[size];
19346 
19347 #ifdef HAVE_MPI
19348  SU2_MPI::Allreduce(&nLocalElem, &MaxLocalElem, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
19349  SU2_MPI::Gather(&Buffer_Send_nElem, 1, MPI_UNSIGNED_LONG, Buffer_Recv_nElem, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
19350 #else
19351  MaxLocalElem = nLocalElem;
19352  Buffer_Recv_nElem[0] = Buffer_Send_nElem[0];
19353 #endif
19354 
19355  nBuffer_Scalar = MaxLocalElem*NODES_PER_ELEMENT;
19356 
19357  /*--- Send and Recv buffers ---*/
19358 
19359  unsigned long *Buffer_Send_Elem = new unsigned long[nBuffer_Scalar];
19360  unsigned long *Buffer_Recv_Elem = NULL;
19361 
19362  unsigned short *Buffer_Send_Halo = new unsigned short[MaxLocalElem];
19363  unsigned short *Buffer_Recv_Halo = NULL;
19364 
19365  /*--- Prepare the receive buffers on the master node only. ---*/
19366 
19367  if (rank == MASTER_NODE) {
19368  Buffer_Recv_Elem = new unsigned long[size*nBuffer_Scalar];
19369  Buffer_Recv_Halo = new unsigned short[size*MaxLocalElem];
19370  if (MaxLocalElem > 0) Conn_Elem = new int[size*MaxLocalElem*NODES_PER_ELEMENT];
19371  }
19372 
19373  /*--- Loop over all elements in this partition and load the
19374  elements of the current type into the buffer to be sent to
19375  the master node. ---*/
19376 
19377  jNode = 0;
19378  for (iElem = 0; iElem < nLocalElem; iElem++) {
19379 
19380  /*--- Loop over all nodes in this element and load the
19381  connectivity into the send buffer. ---*/
19382  Buffer_Send_Halo[iElem] = false;
19383  for (iNode = 0; iNode < NODES_PER_ELEMENT; iNode++) {
19384 
19385  /*--- Store the global index values directly. ---*/
19386 
19387  Buffer_Send_Elem[jNode] = volumeConn[iElem*NODES_PER_ELEMENT+iNode];
19388 
19389  /*--- Increment jNode as the counter. We need this because iElem
19390  may include other elements that we skip over during this loop. ---*/
19391 
19392  jNode++;
19393  }
19394  }
19395 
19396  /*--- Gather the element connectivity information. ---*/
19397 
19398 #ifdef HAVE_MPI
19399  SU2_MPI::Gather(Buffer_Send_Elem, nBuffer_Scalar, MPI_UNSIGNED_LONG, Buffer_Recv_Elem, nBuffer_Scalar, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
19400  SU2_MPI::Gather(Buffer_Send_Halo, MaxLocalElem, MPI_UNSIGNED_SHORT, Buffer_Recv_Halo, MaxLocalElem, MPI_UNSIGNED_SHORT, MASTER_NODE, MPI_COMM_WORLD);
19401 #else
19402  for (unsigned long iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Elem[iPoint] = Buffer_Send_Elem[iPoint];
19403  for (unsigned long iPoint = 0; iPoint < MaxLocalElem; iPoint++) Buffer_Recv_Halo[iPoint] = Buffer_Send_Halo[iPoint];
19404 #endif
19405 
19406  /*--- The master node unpacks and sorts the connectivity. ---*/
19407 
19408  if (rank == MASTER_NODE) {
19409 
19410  /*--- We need to remove any duplicate elements (halo cells) that
19411  exist on multiple partitions. Start by initializing all elements
19412  to the "write" state by using a boolean array. ---*/
19413 
19414  Write_Elem = new bool[size*MaxLocalElem];
19415  for (iElem = 0; iElem < size*MaxLocalElem; iElem++) {
19416  Write_Elem[iElem] = true;
19417  }
19418 
19419  /*--- Remove the rind layer from the solution only if requested ---*/
19420 
19421  if (!Wrt_Halo) {
19422 
19423  /*--- Loop for flagging duplicate elements so that they are not
19424  included in the final connectivity list. ---*/
19425 
19426  kElem = 0;
19427  for (iProcessor = 0; iProcessor < size; iProcessor++) {
19428  for (iElem = 0; iElem < Buffer_Recv_nElem[iProcessor]; iElem++) {
19429 
19430  /*--- Check if this element was marked as a halo. ---*/
19431  if (Buffer_Recv_Halo[kElem+iElem])
19432  Write_Elem[kElem+iElem] = false;
19433 
19434  }
19435  kElem = (iProcessor+1)*MaxLocalElem;
19436  }
19437  }
19438 
19439  /*--- Store the unique connectivity list for this element type. ---*/
19440 
19441  jNode = 0; kNode = 0; jElem = 0; nElem_Total = 0;
19442  for (iProcessor = 0; iProcessor < size; iProcessor++) {
19443  for (iElem = 0; iElem < Buffer_Recv_nElem[iProcessor]; iElem++) {
19444 
19445  /*--- Only write the elements that were flagged for it. ---*/
19446  if (Write_Elem[jElem+iElem]) {
19447 
19448  /*--- Increment total count for this element type ---*/
19449  nElem_Total++;
19450 
19451  /*--- Get global index, then loop over each variable and store.
19452  Note that we are adding one to the index value because CGNS/Tecplot
19453  use 1-based indexing.---*/
19454 
19455  for (iNode = 0; iNode < NODES_PER_ELEMENT; iNode++) {
19456  Conn_Elem[kNode] = (int)Buffer_Recv_Elem[jNode+iElem*NODES_PER_ELEMENT+iNode] + 1;
19457  kNode++;
19458  }
19459  }
19460  }
19461  /*--- Adjust jNode to index of next proc's data in the buffers. ---*/
19462  jElem = (iProcessor+1)*MaxLocalElem;
19463  jNode = (iProcessor+1)*nBuffer_Scalar;
19464  }
19465  }
19466 
19467  /*--- Immediately release the temporary buffers. ---*/
19468  delete [] Buffer_Send_Elem;
19469  delete [] Buffer_Send_Halo;
19470  if (rank == MASTER_NODE) {
19471  delete [] Buffer_Recv_nElem;
19472  delete [] Buffer_Recv_Elem;
19473  delete [] Buffer_Recv_Halo;
19474  delete [] Write_Elem;
19475  }
19476 
19477  /*--- Store the particular global element count in the class data,
19478  and set the class data pointer to the connectivity array. ---*/
19479 
19480  if (rank == MASTER_NODE) {
19481  switch (Elem_Type) {
19482  case TRIANGLE:
19483  nGlobal_Tria = nElem_Total;
19484  if (nGlobal_Tria > 0) Conn_Tria = Conn_Elem;
19485  break;
19486  case QUADRILATERAL:
19487  nGlobal_Quad = nElem_Total;
19488  if (nGlobal_Quad > 0) Conn_Quad = Conn_Elem;
19489  break;
19490  case TETRAHEDRON:
19491  nGlobal_Tetr = nElem_Total;
19492  if (nGlobal_Tetr > 0) Conn_Tetr = Conn_Elem;
19493  break;
19494  case HEXAHEDRON:
19495  nGlobal_Hexa = nElem_Total;
19496  if (nGlobal_Hexa > 0) Conn_Hexa = Conn_Elem;
19497  break;
19498  case PRISM:
19499  nGlobal_Pris = nElem_Total;
19500  if (nGlobal_Pris > 0) Conn_Pris = Conn_Elem;
19501  break;
19502  case PYRAMID:
19503  nGlobal_Pyra = nElem_Total;
19504  if (nGlobal_Pyra > 0) Conn_Pyra = Conn_Elem;
19505  break;
19506  default:
19507  SU2_MPI::Error("Unrecognized element type", CURRENT_FUNCTION);
19508  }
19509  }
19510 
19511 }
19512 
19513 void COutputLegacy::MergeSurfaceConnectivity_FEM(CConfig *config, CGeometry *geometry, unsigned short Elem_Type) {
19514 
19515  unsigned short NODES_PER_ELEMENT = 0;
19516 
19517  unsigned long iNode, jNode;
19518  unsigned long iElem = 0;
19519  unsigned long nLocalElem = 0, nElem_Total = 0;
19520 
19521  int iProcessor;
19522  unsigned long jElem;
19523 
19524  unsigned long Buffer_Send_nElem[1], *Buffer_Recv_nElem = NULL;
19525  unsigned long nBuffer_Scalar = 0;
19526  unsigned long kNode = 0, kElem = 0;
19527  unsigned long MaxLocalElem = 0;
19528 
19529  bool Wrt_Halo = config->GetWrt_Halo();
19530  bool *Write_Elem = NULL;
19531 
19532  int *Conn_Elem = NULL;
19533 
19534  /*--- Create an object of the class CMeshFEM_DG and retrieve the necessary
19535  geometrical information for the FEM DG solver. ---*/
19536  CMeshFEM_DG *DGGeometry = dynamic_cast<CMeshFEM_DG *>(geometry);
19537 
19538  unsigned long nVolElemOwned = DGGeometry->GetNVolElemOwned();
19539 
19540  CVolumeElementFEM *volElem = DGGeometry->GetVolElem();
19541 
19542  const CBoundaryFEM *boundaries = DGGeometry->GetBoundaries();
19543 
19544  const CFEMStandardBoundaryFace *standardBoundaryFacesSol = DGGeometry->GetStandardBoundaryFacesSol();
19545 
19546  /*--- Create the map from the global DOF ID to the local index. ---*/
19547  map<unsigned long, unsigned long> mapLocal2Global;
19548  unsigned long ii = 0;
19549  for(unsigned long i=0; i<nVolElemOwned; ++i) {
19550  for(unsigned short j=0; j<volElem[i].nDOFsSol; ++j, ++ii) {
19551  mapLocal2Global[ii] = volElem[i].offsetDOFsSolGlobal+j;
19552  }
19553  }
19554 
19555  /* Define the vectors for the connectivity of the local linear subelements. */
19556  vector<unsigned long> surfaceConn;
19557 
19558  /*--- Counter for keeping track of the number of this element locally. ---*/
19559  nLocalElem = 0;
19560 
19561  /* Loop over the boundary markers. */
19562  for(unsigned short iMarker=0; iMarker < config->GetnMarker_All(); ++iMarker) {
19563  if( !boundaries[iMarker].periodicBoundary ) {
19564 
19565  /* Check for markers to be plotted. */
19566  if (config->GetMarker_All_Plotting(iMarker) == YES) {
19567 
19568  /* Loop over the surface elements of this marker. */
19569  const vector<CSurfaceElementFEM> &surfElem = boundaries[iMarker].surfElem;
19570  for(unsigned long i=0; i<surfElem.size(); ++i) {
19571 
19572  /* Determine the necessary data from the corresponding standard face,
19573  such as the number of linear subfaces, the number of DOFs per
19574  linear subface and the corresponding local connectivity. */
19575  const unsigned short ind = surfElem[i].indStandardElement;
19576  const unsigned short VTK_Type = standardBoundaryFacesSol[ind].GetVTK_Type();
19577 
19578  /*--- Only store the linear sub-elements if they are of
19579  the current type that we are merging. ---*/
19580  if (VTK_Type == Elem_Type) {
19581 
19582  const unsigned short nSubFaces = standardBoundaryFacesSol[ind].GetNSubFaces();
19583  const unsigned short nDOFsPerFace = standardBoundaryFacesSol[ind].GetNDOFsPerSubFace();
19584  const unsigned short *connSubFaces = standardBoundaryFacesSol[ind].GetSubFaceConn();
19585 
19586  /* Loop over the number of subfaces and store the required data. */
19587  unsigned short ii = 0;
19588  for(unsigned short j=0; j<nSubFaces; ++j) {
19589 
19590  /*--- Store the global index for the surface conn ---*/
19591  for(unsigned short k=0; k<nDOFsPerFace; ++k, ++ii)
19592  surfaceConn.push_back(mapLocal2Global[surfElem[i].DOFsSolFace[connSubFaces[ii]]]);
19593 
19594  nLocalElem++;
19595  }
19596  }
19597  }
19598  }
19599  }
19600  }
19601 
19602  switch (Elem_Type) {
19603  case LINE:
19604  NODES_PER_ELEMENT = N_POINTS_LINE;
19605  break;
19606  case TRIANGLE:
19607  NODES_PER_ELEMENT = N_POINTS_TRIANGLE;
19608  break;
19609  case QUADRILATERAL:
19610  NODES_PER_ELEMENT = N_POINTS_QUADRILATERAL;
19611  break;
19612  default:
19613  SU2_MPI::Error("Unrecognized element type", CURRENT_FUNCTION);
19614  }
19615 
19616  /*--- Find the max number of this element type among all
19617  partitions and set up buffers. ---*/
19618 
19619  Buffer_Send_nElem[0] = nLocalElem;
19620  if (rank == MASTER_NODE) Buffer_Recv_nElem = new unsigned long[size];
19621 
19622 #ifdef HAVE_MPI
19623  SU2_MPI::Allreduce(&nLocalElem, &MaxLocalElem, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
19624  SU2_MPI::Gather(&Buffer_Send_nElem, 1, MPI_UNSIGNED_LONG, Buffer_Recv_nElem, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
19625 #else
19626  MaxLocalElem = nLocalElem;
19627  Buffer_Recv_nElem[0] = Buffer_Send_nElem[0];
19628 #endif
19629 
19630  nBuffer_Scalar = MaxLocalElem*NODES_PER_ELEMENT;
19631 
19632  /*--- Send and Recv buffers ---*/
19633 
19634  unsigned long *Buffer_Send_Elem = new unsigned long[nBuffer_Scalar];
19635  unsigned long *Buffer_Recv_Elem = NULL;
19636 
19637  unsigned short *Buffer_Send_Halo = new unsigned short[MaxLocalElem];
19638  unsigned short *Buffer_Recv_Halo = NULL;
19639 
19640  /*--- Prepare the receive buffers on the master node only. ---*/
19641 
19642  if (rank == MASTER_NODE) {
19643  Buffer_Recv_Elem = new unsigned long[size*nBuffer_Scalar];
19644  Buffer_Recv_Halo = new unsigned short[size*MaxLocalElem];
19645  if (MaxLocalElem > 0) Conn_Elem = new int[size*MaxLocalElem*NODES_PER_ELEMENT];
19646  }
19647 
19648  /*--- Loop over all elements in this partition and load the
19649  elements of the current type into the buffer to be sent to
19650  the master node. ---*/
19651  jNode = 0;
19652  for (iElem = 0; iElem < nLocalElem; iElem++) {
19653 
19654  /*--- Loop over all nodes in this element and load the
19655  connectivity into the send buffer. ---*/
19656  Buffer_Send_Halo[iElem] = false;
19657  for (iNode = 0; iNode < NODES_PER_ELEMENT; iNode++) {
19658 
19659  /*--- Store the global index values directly. ---*/
19660  Buffer_Send_Elem[jNode] = surfaceConn[iElem*NODES_PER_ELEMENT+iNode];
19661 
19662  /*--- Increment jNode as the counter for the buffer array. ---*/
19663  jNode++;
19664  }
19665  }
19666 
19667  /*--- Gather the element connectivity information. ---*/
19668 
19669 #ifdef HAVE_MPI
19670  SU2_MPI::Gather(Buffer_Send_Elem, nBuffer_Scalar, MPI_UNSIGNED_LONG, Buffer_Recv_Elem, nBuffer_Scalar, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
19671  SU2_MPI::Gather(Buffer_Send_Halo, MaxLocalElem, MPI_UNSIGNED_SHORT, Buffer_Recv_Halo, MaxLocalElem, MPI_UNSIGNED_SHORT, MASTER_NODE, MPI_COMM_WORLD);
19672 #else
19673  for (unsigned long iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Elem[iPoint] = Buffer_Send_Elem[iPoint];
19674  for (unsigned long iPoint = 0; iPoint < MaxLocalElem; iPoint++) Buffer_Recv_Halo[iPoint] = Buffer_Send_Halo[iPoint];
19675 #endif
19676 
19677  /*--- The master node unpacks and sorts the connectivity. ---*/
19678 
19679  if (rank == MASTER_NODE) {
19680 
19681  /*--- We need to remove any duplicate elements (halo cells) that
19682  exist on multiple partitions. Start by initializing all elements
19683  to the "write" state by using a boolean array. ---*/
19684 
19685  Write_Elem = new bool[size*MaxLocalElem];
19686  for (iElem = 0; iElem < size*MaxLocalElem; iElem++) {
19687  Write_Elem[iElem] = true;
19688  }
19689 
19690  /*--- Remove the rind layer from the solution only if requested ---*/
19691 
19692  if (!Wrt_Halo) {
19693 
19694  /*--- Loop for flagging duplicate elements so that they are not
19695  included in the final connectivity list. ---*/
19696 
19697  kElem = 0;
19698  for (iProcessor = 0; iProcessor < size; iProcessor++) {
19699  for (iElem = 0; iElem < Buffer_Recv_nElem[iProcessor]; iElem++) {
19700 
19701  /*--- Check if this element was marked as a halo. ---*/
19702  if (Buffer_Recv_Halo[kElem+iElem])
19703  Write_Elem[kElem+iElem] = false;
19704 
19705  }
19706  kElem = (iProcessor+1)*MaxLocalElem;
19707  }
19708  }
19709 
19710  /*--- Store the unique connectivity list for this element type. ---*/
19711 
19712  jNode = 0; kNode = 0; jElem = 0; nElem_Total = 0;
19713  for (iProcessor = 0; iProcessor < size; iProcessor++) {
19714  for (iElem = 0; iElem < Buffer_Recv_nElem[iProcessor]; iElem++) {
19715 
19716  /*--- Only write the elements that were flagged for it. ---*/
19717  if (Write_Elem[jElem+iElem]) {
19718 
19719  /*--- Increment total count for this element type ---*/
19720  nElem_Total++;
19721 
19722  /*--- Get global index, then loop over each variable and store.
19723  Note that we are adding one to the index value because CGNS/Tecplot
19724  use 1-based indexing.---*/
19725 
19726  for (iNode = 0; iNode < NODES_PER_ELEMENT; iNode++) {
19727  Conn_Elem[kNode] = (int)Buffer_Recv_Elem[jNode+iElem*NODES_PER_ELEMENT+iNode] + 1;
19728  kNode++;
19729  }
19730  }
19731  }
19732  /*--- Adjust jNode to index of next proc's data in the buffers. ---*/
19733  jElem = (iProcessor+1)*MaxLocalElem;
19734  jNode = (iProcessor+1)*nBuffer_Scalar;
19735  }
19736  }
19737 
19738  /*--- Immediately release the temporary buffers. ---*/
19739  delete [] Buffer_Send_Elem;
19740  delete [] Buffer_Send_Halo;
19741  if (rank == MASTER_NODE) {
19742  delete [] Buffer_Recv_nElem;
19743  delete [] Buffer_Recv_Elem;
19744  delete [] Buffer_Recv_Halo;
19745  delete [] Write_Elem;
19746  }
19747 
19748  /*--- Store the particular global element count in the class data,
19749  and set the class data pointer to the connectivity array. ---*/
19750 
19751  if (rank == MASTER_NODE) {
19752  switch (Elem_Type) {
19753  case LINE:
19754  nGlobal_Line = nElem_Total;
19755  if (nGlobal_Line > 0) Conn_Line = Conn_Elem;
19756  break;
19757  case TRIANGLE:
19758  nGlobal_BoundTria = nElem_Total;
19759  if (nGlobal_BoundTria > 0) Conn_BoundTria = Conn_Elem;
19760  break;
19761  case QUADRILATERAL:
19762  nGlobal_BoundQuad = nElem_Total;
19763  if (nGlobal_BoundQuad > 0) Conn_BoundQuad = Conn_Elem;
19764  break;
19765  default:
19766  SU2_MPI::Error("Unrecognized element type", CURRENT_FUNCTION);
19767  }
19768  }
19769 }
19770 
19771 void COutputLegacy::MergeSolution_FEM(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone) {
19772 
19773  unsigned short Kind_Solver = config->GetKind_Solver();
19774  unsigned short iVar = 0, FirstIndex = NONE, SecondIndex = NONE, ThirdIndex = NONE;
19775  unsigned short nVar_First = 0, nVar_Second = 0, nVar_Third = 0;
19776 
19777  unsigned long iPoint = 0, jPoint = 0;
19778 
19779  unsigned long Buffer_Send_nPoint[1], *Buffer_Recv_nPoint = NULL;
19780  unsigned long nLocalPoint = 0, MaxLocalPoint = 0;
19781  unsigned long iGlobal_Index = 0, nBuffer_Scalar = 0;
19782 
19783  int iProcessor;
19784 
19785  /*--- Prepare send buffers for the conservative variables. Need to
19786  find the total number of conservative variables and also the
19787  index for their particular solution container. ---*/
19788 
19789  switch (Kind_Solver) {
19790  case FEM_EULER : case FEM_NAVIER_STOKES: case FEM_LES: FirstIndex = FLOW_SOL; SecondIndex = NONE; ThirdIndex = NONE; break;
19791  default: SecondIndex = NONE; ThirdIndex = NONE; break;
19792  }
19793 
19794  nVar_First = solver[FirstIndex]->GetnVar();
19795  if (SecondIndex != NONE) nVar_Second = solver[SecondIndex]->GetnVar();
19796  if (ThirdIndex != NONE) nVar_Third = solver[ThirdIndex]->GetnVar();
19797  nVar_Consv = nVar_First + nVar_Second + nVar_Third;
19798  nVar_Total = nVar_Consv;
19799 
19800  /*--- Create an object of the class CMeshFEM_DG and retrieve the necessary
19801  geometrical information for the FEM DG solver. ---*/
19802  CMeshFEM_DG *DGGeometry = dynamic_cast<CMeshFEM_DG *>(geometry);
19803 
19804  unsigned long nVolElemOwned = DGGeometry->GetNVolElemOwned();
19805  CVolumeElementFEM *volElem = DGGeometry->GetVolElem();
19806 
19807  /*--- Create the map from the global DOF ID to the local index. ---*/
19808  map<unsigned long, unsigned long> mapLocal2Global;
19809  vector<su2double> DOFsSol;
19810  vector<unsigned long> globalID;
19811 
19812  /*--- Update the solution by looping over the owned volume elements. ---*/
19813  for(unsigned long l=0; l<nVolElemOwned; ++l) {
19814 
19815  /* Set the pointers for the residual and solution for this element. */
19816  const unsigned long offset = nVar_Consv*volElem[l].offsetDOFsSolLocal;
19817  su2double *solDOFs = solver[FirstIndex]->GetVecSolDOFs() + offset;
19818 
19819  /* Loop over the DOFs for this element and store the solution. */
19820 
19821  unsigned int i = 0;
19822  for(unsigned short j=0; j<volElem[l].nDOFsSol; ++j) {
19823 
19824  nLocalPoint++;
19825  const unsigned long globalIndex = volElem[l].offsetDOFsSolGlobal + j;
19826  globalID.push_back(globalIndex);
19827 
19828  for(unsigned short iVar=0; iVar<nVar_Consv; ++iVar, ++i) {
19829  DOFsSol.push_back(solDOFs[i]);
19830  }
19831  }
19832  }
19833  Buffer_Send_nPoint[0] = nLocalPoint;
19834 
19835  /*--- Each processor sends its local number of nodes to the master. ---*/
19836 
19837  if (rank == MASTER_NODE) Buffer_Recv_nPoint = new unsigned long[size];
19838 
19839 #ifdef HAVE_MPI
19840  SU2_MPI::Allreduce(&nLocalPoint, &MaxLocalPoint, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
19841  SU2_MPI::Gather(&Buffer_Send_nPoint, 1, MPI_UNSIGNED_LONG, Buffer_Recv_nPoint, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
19842 #else
19843  MaxLocalPoint = nLocalPoint;
19844  Buffer_Recv_nPoint[0] = Buffer_Send_nPoint[0];
19845 #endif
19846 
19847  nBuffer_Scalar = MaxLocalPoint;
19848 
19849  /*--- Send and Recv buffers. ---*/
19850 
19851  su2double *Buffer_Send_Var = new su2double[MaxLocalPoint];
19852  su2double *Buffer_Recv_Var = NULL;
19853 
19854  unsigned long *Buffer_Send_GlobalIndex = new unsigned long[MaxLocalPoint];
19855  unsigned long *Buffer_Recv_GlobalIndex = NULL;
19856 
19857  /*--- Prepare the receive buffers in the master node only. ---*/
19858 
19859  if (rank == MASTER_NODE) {
19860 
19861  Buffer_Recv_Var = new su2double[size*MaxLocalPoint];
19862  Buffer_Recv_GlobalIndex = new unsigned long[size*MaxLocalPoint];
19863 
19864  /*--- Sum total number of nodes to be written and allocate arrays ---*/
19865  nGlobal_Poin = 0;
19866  for (iProcessor = 0; iProcessor < size; iProcessor++) {
19867  nGlobal_Poin += Buffer_Recv_nPoint[iProcessor];
19868  }
19869  Data = new su2double*[nVar_Total];
19870  for (iVar = 0; iVar < nVar_Total; iVar++) {
19871  Data[iVar] = new su2double[nGlobal_Poin];
19872  }
19873  }
19874 
19875  /*--- Main communication routine. Loop over each variable that has
19876  been requested by the user and perform the MPI comm. Temporary
19877  1-D buffers are used to send the solution for each variable at all
19878  nodes on each partition to the master node. These are then unpacked
19879  by the master and sorted by global index in one large n-dim. array. ---*/
19880 
19881  for (iVar = 0; iVar < nVar_Consv; iVar++) {
19882 
19883  /*--- Loop over this partition to collect the current variable ---*/
19884 
19885  jPoint = 0;
19886  for (iPoint = 0; iPoint < nLocalPoint; iPoint++) {
19887 
19888  /*--- Get this variable into the temporary send buffer. ---*/
19889 
19890  Buffer_Send_Var[jPoint] = DOFsSol[iPoint*nVar_Consv+iVar];
19891 
19892  /*--- Only send/recv the volumes & global indices during the first loop ---*/
19893 
19894  if (iVar == 0) {
19895  Buffer_Send_GlobalIndex[jPoint] = globalID[iPoint];
19896  }
19897 
19898  jPoint++;
19899 
19900  }
19901 
19902  /*--- Gather the data on the master node. ---*/
19903 
19904 #ifdef HAVE_MPI
19905  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
19906 #else
19907  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint];
19908 #endif
19909 
19910  if (iVar == 0) {
19911 #ifdef HAVE_MPI
19912  SU2_MPI::Gather(Buffer_Send_GlobalIndex, nBuffer_Scalar, MPI_UNSIGNED_LONG, Buffer_Recv_GlobalIndex, nBuffer_Scalar, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
19913 #else
19914  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_GlobalIndex[iPoint] = Buffer_Send_GlobalIndex[iPoint];
19915 #endif
19916  }
19917 
19918  /*--- The master node unpacks and sorts this variable by global index ---*/
19919 
19920  if (rank == MASTER_NODE) {
19921  jPoint = 0;
19922  for (iProcessor = 0; iProcessor < size; iProcessor++) {
19923  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
19924 
19925  /*--- Get global index, then loop over each variable and store ---*/
19926 
19927  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
19928 
19929  Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint];
19930 
19931  jPoint++;
19932 
19933  }
19934  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
19935  jPoint = (iProcessor+1)*nBuffer_Scalar;
19936  }
19937  }
19938 
19939  }
19940 
19941  /*--- Immediately release the temporary buffers. ---*/
19942 
19943  delete [] Buffer_Send_Var;
19944  delete [] Buffer_Send_GlobalIndex;
19945  if (rank == MASTER_NODE) {
19946  delete [] Buffer_Recv_nPoint;
19947  delete [] Buffer_Recv_Var;
19948  delete [] Buffer_Recv_GlobalIndex;
19949  }
19950 
19951 }
19952 
19953 void COutputLegacy::MergeBaselineSolution_FEM(CConfig *config, CGeometry *geometry, CSolver *solver, unsigned short val_iZone) {
19954 
19955  /*--- Local variables needed on all processors ---*/
19956  unsigned short iVar;
19957  unsigned long iPoint = 0, jPoint = 0;
19958 
19959  unsigned long Buffer_Send_nPoint[1], *Buffer_Recv_nPoint = NULL;
19960  unsigned long nLocalPoint = 0, MaxLocalPoint = 0;
19961  unsigned long iGlobal_Index = 0, nBuffer_Scalar = 0;
19962 
19963  int iProcessor;
19964 
19965  /*--- We know the number of fields from reading the restart. ---*/
19966 
19967  nVar_Total = config->fields.size() - 1;
19968 
19969  /*--- Create an object of the class CMeshFEM_DG and retrieve the necessary
19970  geometrical information for the FEM DG solver. ---*/
19971  CMeshFEM_DG *DGGeometry = dynamic_cast<CMeshFEM_DG *>(geometry);
19972 
19973  unsigned long nVolElemOwned = DGGeometry->GetNVolElemOwned();
19974  CVolumeElementFEM *volElem = DGGeometry->GetVolElem();
19975 
19976  /*--- Create the map from the global DOF ID to the local index. ---*/
19977  vector<su2double> DOFsSol;
19978  vector<unsigned long> globalID;
19979 
19980  /*--- Update the solution by looping over the owned volume elements. ---*/
19981  for(unsigned long l=0; l<nVolElemOwned; ++l) {
19982 
19983  /* Set the pointers for the residual and solution for this element. */
19984  const unsigned long offset = nVar_Total*volElem[l].offsetDOFsSolLocal;
19985  su2double *solDOFs = solver->GetVecSolDOFs() + offset;
19986 
19987  /* Loop over the DOFs for this element and store the solution. */
19988 
19989  unsigned int i = 0;
19990  for(unsigned short j=0; j<volElem[l].nDOFsSol; ++j) {
19991 
19992  nLocalPoint++;
19993  const unsigned long globalIndex = volElem[l].offsetDOFsSolGlobal + j;
19994  globalID.push_back(globalIndex);
19995 
19996  for(unsigned short iVar=0; iVar<nVar_Total; ++iVar, ++i) {
19997  DOFsSol.push_back(solDOFs[i]);
19998  }
19999  }
20000  }
20001  Buffer_Send_nPoint[0] = nLocalPoint;
20002 
20003  /*--- Each processor sends its local number of nodes to the master. ---*/
20004 
20005  if (rank == MASTER_NODE) Buffer_Recv_nPoint = new unsigned long[size];
20006 
20007 #ifdef HAVE_MPI
20008  SU2_MPI::Allreduce(&nLocalPoint, &MaxLocalPoint, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
20009  SU2_MPI::Gather(&Buffer_Send_nPoint, 1, MPI_UNSIGNED_LONG, Buffer_Recv_nPoint, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
20010 #else
20011  MaxLocalPoint = nLocalPoint;
20012  Buffer_Recv_nPoint[0] = Buffer_Send_nPoint[0];
20013 #endif
20014 
20015  nBuffer_Scalar = MaxLocalPoint;
20016 
20017  /*--- Send and Recv buffers. ---*/
20018 
20019  su2double *Buffer_Send_Var = new su2double[MaxLocalPoint];
20020  su2double *Buffer_Recv_Var = NULL;
20021 
20022  unsigned long *Buffer_Send_GlobalIndex = new unsigned long[MaxLocalPoint];
20023  unsigned long *Buffer_Recv_GlobalIndex = NULL;
20024 
20025  /*--- Prepare the receive buffers in the master node only. ---*/
20026 
20027  if (rank == MASTER_NODE) {
20028 
20029  Buffer_Recv_Var = new su2double[size*MaxLocalPoint];
20030  Buffer_Recv_GlobalIndex = new unsigned long[size*MaxLocalPoint];
20031 
20032  /*--- Sum total number of nodes to be written and allocate arrays ---*/
20033  nGlobal_Poin = 0;
20034  for (iProcessor = 0; iProcessor < size; iProcessor++) {
20035  nGlobal_Poin += Buffer_Recv_nPoint[iProcessor];
20036  }
20037  Data = new su2double*[nVar_Total];
20038  for (iVar = 0; iVar < nVar_Total; iVar++) {
20039  Data[iVar] = new su2double[nGlobal_Poin];
20040  }
20041  }
20042 
20043  /*--- Main communication routine. Loop over each variable that has
20044  been requested by the user and perform the MPI comm. Temporary
20045  1-D buffers are used to send the solution for each variable at all
20046  nodes on each partition to the master node. These are then unpacked
20047  by the master and sorted by global index in one large n-dim. array. ---*/
20048 
20049  for (iVar = 0; iVar < nVar_Total; iVar++) {
20050 
20051  /*--- Loop over this partition to collect the current variable ---*/
20052 
20053  jPoint = 0;
20054  for (iPoint = 0; iPoint < nLocalPoint; iPoint++) {
20055 
20056  /*--- Get this variable into the temporary send buffer. ---*/
20057 
20058  Buffer_Send_Var[jPoint] = DOFsSol[iPoint*nVar_Total+iVar];
20059 
20060  /*--- Only send/recv the volumes & global indices during the first loop ---*/
20061 
20062  if (iVar == 0) {
20063  Buffer_Send_GlobalIndex[jPoint] = globalID[iPoint];
20064  }
20065 
20066  jPoint++;
20067 
20068  }
20069 
20070  /*--- Gather the data on the master node. ---*/
20071 
20072 #ifdef HAVE_MPI
20073  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
20074 #else
20075  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint];
20076 #endif
20077 
20078  if (iVar == 0) {
20079 #ifdef HAVE_MPI
20080  SU2_MPI::Gather(Buffer_Send_GlobalIndex, nBuffer_Scalar, MPI_UNSIGNED_LONG, Buffer_Recv_GlobalIndex, nBuffer_Scalar, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
20081 #else
20082  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_GlobalIndex[iPoint] = Buffer_Send_GlobalIndex[iPoint];
20083 #endif
20084  }
20085 
20086  /*--- The master node unpacks and sorts this variable by global index ---*/
20087 
20088  if (rank == MASTER_NODE) {
20089  jPoint = 0;
20090  for (iProcessor = 0; iProcessor < size; iProcessor++) {
20091  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
20092 
20093  /*--- Get global index, then loop over each variable and store ---*/
20094 
20095  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
20096 
20097  Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint];
20098 
20099  jPoint++;
20100 
20101  }
20102  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
20103  jPoint = (iProcessor+1)*nBuffer_Scalar;
20104  }
20105  }
20106 
20107  }
20108 
20109  /*--- Immediately release the temporary buffers. ---*/
20110 
20111  delete [] Buffer_Send_Var;
20112  delete [] Buffer_Send_GlobalIndex;
20113  if (rank == MASTER_NODE) {
20114  delete [] Buffer_Recv_nPoint;
20115  delete [] Buffer_Recv_Var;
20116  delete [] Buffer_Recv_GlobalIndex;
20117  }
20118 
20119 }
20120 
20121 void COutputLegacy::SetResult_Files_FEM(CSolver ****solver_container, CGeometry ***geometry, CConfig **config,
20122  unsigned long iExtIter, unsigned short val_nZone) {
20123 
20124  unsigned short iZone;
20125 
20126  for (iZone = 0; iZone < val_nZone; iZone++) {
20127 
20128  /*--- Check whether we are writing any output at all. We can
20129  disable all output to avoid serial bottleneck at scale. ---*/
20130  if (config[iZone]->GetWrt_Output()) {
20131 
20132  /*--- Flags identifying the types of files to be written. ---*/
20133 
20134  bool Wrt_Vol = config[iZone]->GetWrt_Vol_Sol();
20135  bool Wrt_Srf = config[iZone]->GetWrt_Srf_Sol();
20136 
20137  /*--- Get the file output format ---*/
20138 
20139  unsigned short FileFormat = config[iZone]->GetTabular_FileFormat();
20140 
20141  /*--- Merge the node coordinates and connectivity, if necessary. This
20142  is only performed if a volume solution file is requested, and it
20143  is active by default. ---*/
20144 
20145  if (Wrt_Vol || Wrt_Srf) {
20146  if (rank == MASTER_NODE) cout << endl << "Merging connectivities in the Master node." << endl;
20147  MergeConnectivity_FEM(config[iZone], geometry[iZone][MESH_0], iZone);
20148  }
20149 
20150  /*--- Merge coordinates of all grid nodes (excluding ghost points).
20151  The grid coordinates are always merged and included first in the
20152  restart files. ---*/
20153 
20154  if (rank == MASTER_NODE) cout << "Merging coordinates in the Master node." << endl;
20155  MergeCoordinates_FEM(config[iZone], geometry[iZone][MESH_0]);
20156 
20157  if ((rank == MASTER_NODE) && (Wrt_Vol || Wrt_Srf)) {
20158  if (FileFormat == TECPLOT_BINARY) {
20159  if (rank == MASTER_NODE) cout << "Writing Tecplot binary volume and surface mesh files." << endl;
20160 // SetTecplotBinary_DomainMesh(config[iZone], geometry[iZone][MESH_0], iZone);
20161 // SetTecplotBinary_SurfaceMesh(config[iZone], geometry[iZone][MESH_0], iZone);
20162  }
20163  }
20164 
20165  /*--- Merge the solution data needed for volume solutions and restarts ---*/
20166 
20167  if (rank == MASTER_NODE) cout << "Merging solution in the Master node." << endl;
20168  MergeSolution_FEM(config[iZone], geometry[iZone][MESH_0], solver_container[iZone][MESH_0], iZone);
20169 
20170  /*--- Write restart, or Tecplot files using the merged data.
20171  This data lives only on the master, and these routines are currently
20172  executed by the master proc alone (as if in serial). ---*/
20173 
20174  if (rank == MASTER_NODE) {
20175 
20176  /*--- Write a native restart file ---*/
20177 
20178  if (rank == MASTER_NODE) cout << "Writing SU2 native restart file." << endl;
20179  SetRestart(config[iZone], geometry[iZone][MESH_0], solver_container[iZone][MESH_0] , iZone);
20180 
20181  if (Wrt_Vol) {
20182 
20183  switch (FileFormat) {
20184 
20185  case TECPLOT:
20186 
20187  /*--- Write a Tecplot ASCII file ---*/
20188 
20189  if (rank == MASTER_NODE) cout << "Writing Tecplot ASCII file volume solution file." << endl;
20190 // SetTecplotASCII(config[iZone], geometry[iZone][MESH_0], solver_container[iZone][MESH_0], iZone, val_nZone, false);
20191  DeallocateConnectivity(config[iZone], geometry[iZone][MESH_0], false);
20192  break;
20193 
20194 
20195  case TECPLOT_BINARY:
20196 
20197  /*--- Write a Tecplot binary solution file ---*/
20198 
20199  if (rank == MASTER_NODE) cout << "Writing Tecplot binary volume solution file." << endl;
20200 // SetTecplotBinary_DomainSolution(config[iZone], geometry[iZone][MESH_0], iZone);
20201  DeallocateConnectivity(config[iZone], geometry[iZone][MESH_0], false);
20202  break;
20203 
20204 
20205  case PARAVIEW:
20206 
20207  /*--- Write a Paraview ASCII file ---*/
20208 
20209  if (rank == MASTER_NODE) cout << "Writing Paraview ASCII volume solution file." << endl;
20210 // SetParaview_ASCII(config[iZone], geometry[iZone][MESH_0], iZone, val_nZone, false);
20211  DeallocateConnectivity(config[iZone], geometry[iZone][MESH_0], false);
20212  break;
20213 
20214  case PARAVIEW_BINARY:
20215 
20216  /*--- Write a ParaView ASCII file instead for now. ---*/
20217 
20218  if (rank == MASTER_NODE) cout << "ParaView binary volume files not available in this mode." << endl;
20219  if (rank == MASTER_NODE) cout << " Writing ParaView ASCII volume solution file instead." << endl;
20220 // SetParaview_ASCII(config[iZone], geometry[iZone][MESH_0], iZone, val_nZone, false);
20221  DeallocateConnectivity(config[iZone], geometry[iZone][MESH_0], false);
20222  break;
20223 
20224  default:
20225  break;
20226  }
20227 
20228  }
20229 
20230  if (Wrt_Srf) {
20231 
20232  switch (FileFormat) {
20233 
20234  case TECPLOT:
20235 
20236  /*--- Write a Tecplot ASCII file ---*/
20237 
20238  if (rank == MASTER_NODE) cout << "Writing Tecplot ASCII surface solution file." << endl;
20239 // SetTecplotASCII(config[iZone], geometry[iZone][MESH_0], solver_container[iZone][MESH_0] , iZone, val_nZone, true);
20240  DeallocateConnectivity(config[iZone], geometry[iZone][MESH_0], true);
20241  break;
20242 
20243  case TECPLOT_BINARY:
20244 
20245  /*--- Write a Tecplot binary solution file ---*/
20246 
20247  if (rank == MASTER_NODE) cout << "Writing Tecplot binary surface solution file." << endl;
20248 // SetTecplotBinary_SurfaceSolution(config[iZone], geometry[iZone][MESH_0], iZone);
20249  DeallocateConnectivity(config[iZone], geometry[iZone][MESH_0], true);
20250  break;
20251 
20252  case PARAVIEW:
20253 
20254  /*--- Write a Paraview ASCII file ---*/
20255 
20256  if (rank == MASTER_NODE) cout << "Writing Paraview ASCII surface solution file." << endl;
20257 // SetParaview_ASCII(config[iZone], geometry[iZone][MESH_0], iZone, val_nZone, true);
20258  DeallocateConnectivity(config[iZone], geometry[iZone][MESH_0], true);
20259  break;
20260 
20261  case PARAVIEW_BINARY:
20262 
20263  /*--- Write a ParaView ASCII file instead for now. ---*/
20264 
20265  if (rank == MASTER_NODE) cout << "ParaView binary surface files not available in this mode." << endl;
20266  if (rank == MASTER_NODE) cout << " Writing ParaView ASCII surface solution file instead." << endl;
20267 // SetParaview_ASCII(config[iZone], geometry[iZone][MESH_0], iZone, val_nZone, true);
20268  DeallocateConnectivity(config[iZone], geometry[iZone][MESH_0], true);
20269  break;
20270 
20271  default:
20272  break;
20273  }
20274 
20275  }
20276 
20277  /*--- Release memory needed for merging the solution data. ---*/
20278 
20279  DeallocateCoordinates(config[iZone], geometry[iZone][MESH_0]);
20280  DeallocateSolution(config[iZone], geometry[iZone][MESH_0]);
20281 
20282  }
20283 
20284  /*--- Final broadcast (informing other procs that the base output
20285  file was written). ---*/
20286 
20287 #ifdef HAVE_MPI
20290 #endif
20291 
20292  } else {
20293  if (rank == MASTER_NODE) cout << endl << "Restart and solution output disabled." << endl;
20294  }
20295  }
20296 }
20297 
20299  unsigned long iExtIter, unsigned short val_nZone) {
20300 
20301  unsigned short iZone, iInst, nInst;
20302 
20303  for (iZone = 0; iZone < val_nZone; iZone++) {
20304 
20305  nInst = config[iZone]->GetnTimeInstances();
20306 
20307  for (iInst = 0; iInst < nInst; iInst++) {
20308 
20309  config[iZone]->SetiInst(iInst);
20310 
20311  /*--- Flags identifying the types of files to be written. ---*/
20312 
20313  bool Wrt_Vol = config[iZone]->GetWrt_Vol_Sol();
20314  bool Wrt_Srf = config[iZone]->GetWrt_Srf_Sol();
20315 
20316  /*--- Get the file output format ---*/
20317 
20318  unsigned short FileFormat = config[iZone]->GetTabular_FileFormat();
20319 
20320  /*--- Merge the node coordinates and connectivity if necessary. This
20321  is only performed if a volume solution file is requested, and it
20322  is active by default. ---*/
20323 
20324  if ((Wrt_Vol || Wrt_Srf)) {
20325  if (rank == MASTER_NODE) cout << "Merging connectivities in the Master node." << endl;
20326  MergeConnectivity_FEM(config[iZone], geometry[iZone][iInst], iZone);
20327  }
20328 
20329  /*--- Merge the solution data needed for volume solutions and restarts ---*/
20330 
20331  if ((Wrt_Vol || Wrt_Srf)) {
20332  if (rank == MASTER_NODE) cout << "Merging solution in the Master node." << endl;
20333  MergeBaselineSolution_FEM(config[iZone], geometry[iZone][iInst], solver[iZone][iInst], iZone);
20334  }
20335 
20336  /*--- Write restart, Tecplot or Paraview files using the merged data.
20337  This data lives only on the master, and these routines are currently
20338  executed by the master proc alone (as if in serial). ---*/
20339 
20340  if (rank == MASTER_NODE) {
20341 
20342  if (Wrt_Vol) {
20343 
20344  switch (FileFormat) {
20345 
20346  case TECPLOT:
20347 
20348  /*--- Write a Tecplot ASCII file ---*/
20349 
20350  if (rank == MASTER_NODE) cout << "Writing Tecplot ASCII file (volume grid)." << endl;
20351 // SetTecplotASCII(config[iZone], geometry[iZone][iInst], &solver[iZone][iInst], iZone, val_nZone, false);
20352  DeallocateConnectivity(config[iZone], geometry[iZone][iInst], false);
20353  break;
20354 
20355 
20356  case TECPLOT_BINARY:
20357 
20358  /*--- Write a Tecplot binary solution file ---*/
20359 
20360  if (rank == MASTER_NODE) cout << "Writing Tecplot Binary file (volume grid)." << endl;
20361 // SetTecplotBinary_DomainMesh(config[iZone], geometry[iZone][iInst], iZone);
20362 // SetTecplotBinary_DomainSolution(config[iZone], geometry[iZone][iInst], iZone);
20363  break;
20364 
20365 
20366  case PARAVIEW:
20367 
20368  /*--- Write a Paraview ASCII file ---*/
20369 
20370  if (rank == MASTER_NODE) cout << "Writing Paraview ASCII file (volume grid)." << endl;
20371 // SetParaview_ASCII(config[iZone], geometry[iZone][iInst], iZone, val_nZone, false);
20372  DeallocateConnectivity(config[iZone], geometry[iZone][iInst], false);
20373  break;
20374 
20375  case PARAVIEW_BINARY:
20376 
20377  /*--- Write a ParaView ASCII file instead for now. ---*/
20378 
20379  if (rank == MASTER_NODE) cout << "ParaView binary (volume grid) files not available in this mode." << endl;
20380  if (rank == MASTER_NODE) cout << " Writing ParaView ASCII file instead." << endl;
20381 // SetParaview_ASCII(config[iZone], geometry[iZone][iInst], iZone, val_nZone, false);
20382  DeallocateConnectivity(config[iZone], geometry[iZone][iInst], false);
20383  break;
20384 
20385  default:
20386  break;
20387  }
20388 
20389  }
20390 
20391  if (Wrt_Srf) {
20392 
20393  switch (FileFormat) {
20394 
20395  case TECPLOT:
20396 
20397  /*--- Write a Tecplot ASCII file ---*/
20398 
20399  if (rank == MASTER_NODE) cout << "Writing Tecplot ASCII file (surface grid)." << endl;
20400 // SetTecplotASCII(config[iZone], geometry[iZone][iInst], &solver[iZone][iInst], iZone, val_nZone, true);
20401  DeallocateConnectivity(config[iZone], geometry[iZone][iInst], true);
20402  break;
20403 
20404  case TECPLOT_BINARY:
20405 
20406  /*--- Write a Tecplot binary solution file ---*/
20407 
20408  if (rank == MASTER_NODE) cout << "Writing Tecplot Binary file (surface grid)." << endl;
20409 // SetTecplotBinary_SurfaceMesh(config[iZone], geometry[iZone][iInst], iZone);
20410 // SetTecplotBinary_SurfaceSolution(config[iZone], geometry[iZone][iInst], iZone);
20411  break;
20412 
20413  case PARAVIEW:
20414 
20415  /*--- Write a Paraview ASCII file ---*/
20416 
20417  if (rank == MASTER_NODE) cout << "Writing Paraview ASCII file (surface grid)." << endl;
20418 // SetParaview_ASCII(config[iZone], geometry[iZone][iInst], iZone, val_nZone, true);
20419  DeallocateConnectivity(config[iZone], geometry[iZone][iInst], true);
20420  break;
20421 
20422  case PARAVIEW_BINARY:
20423 
20424  /*--- Write a ParaView ASCII file instead for now. ---*/
20425 
20426  if (rank == MASTER_NODE) cout << "ParaView binary (surface grid) files not available in this mode." << endl;
20427  if (rank == MASTER_NODE) cout << " Writing ParaView ASCII file instead." << endl;
20428 // SetParaview_ASCII(config[iZone], geometry[iZone][iInst], iZone, val_nZone, true);
20429  DeallocateConnectivity(config[iZone], geometry[iZone][iInst], true);
20430  break;
20431 
20432  default:
20433  break;
20434  }
20435  }
20436 
20437  if (FileFormat == TECPLOT_BINARY) {
20438  if (!wrote_base_file)
20439  DeallocateConnectivity(config[iZone], geometry[iZone][iInst], false);
20440  if (!wrote_surf_file)
20441  DeallocateConnectivity(config[iZone], geometry[iZone][iInst], wrote_surf_file);
20442  }
20443 
20444  if (Wrt_Vol || Wrt_Srf)
20445  DeallocateSolution(config[iZone], geometry[iZone][iInst]);
20446  }
20447 
20448  /*--- Final broadcast (informing other procs that the base output
20449  file was written). ---*/
20450 
20451 #ifdef HAVE_MPI
20453 #endif
20454  }
20455  }
20456 }
20457 
20458 void COutputLegacy::LoadLocalData_FEM(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone) {
20459 
20460  unsigned short iDim;
20461  unsigned short Kind_Solver = config->GetKind_Solver();
20462  unsigned short nDim = geometry->GetnDim();
20463 
20464  unsigned long iVar, jVar;
20465  unsigned long iPoint, jPoint, FirstIndex = NONE, SecondIndex = NONE;
20466  unsigned long nVar_First = 0, nVar_Second = 0, nVar_Consv_Par = 0;
20467 
20468  stringstream varname;
20469 
20470  /*--- Use a switch statement to decide how many solver containers we have
20471  in this zone for output. ---*/
20472 
20473  switch (Kind_Solver) {
20474  case FEM_EULER : case FEM_NAVIER_STOKES: case FEM_LES: FirstIndex = FLOW_SOL; SecondIndex = NONE; break;
20475  case FEM_RANS : FirstIndex = FLOW_SOL; SecondIndex = TURB_SOL; break;
20476  default: SecondIndex = NONE; break;
20477  }
20478 
20479  nVar_First = solver[FirstIndex]->GetnVar();
20480  if (SecondIndex != NONE) nVar_Second = solver[SecondIndex]->GetnVar();
20481  nVar_Consv_Par = nVar_First + nVar_Second;
20482 
20483  /*--------------------------------------------------------------------------*/
20484  /*--- Step 1: Register the variables that will be output. To register a ---*/
20485  /*--- variable, two things are required. First, increment the ---*/
20486  /*--- counter for the number of variables (nVar_Par), which ---*/
20487  /*--- controls the size of the data structure allocation, i.e., ---*/
20488  /*--- the number of columns in an nPoint x nVar structure. ---*/
20489  /*--- Second, add a name for the variable to the vector that ---*/
20490  /*--- holds the string names. ---*/
20491  /*--------------------------------------------------------------------------*/
20492 
20493  /*--- All output files first need the grid coordinates. ---*/
20494 
20495  nVar_Par = 1; Variable_Names.push_back("x");
20496  nVar_Par += 1; Variable_Names.push_back("y");
20497  if (geometry->GetnDim() == 3) {
20498  nVar_Par += 1; Variable_Names.push_back("z");
20499  }
20500 
20501  /*--- At a mininum, the restarts and visualization files need the
20502  conservative variables, so these follow next. ---*/
20503 
20504  nVar_Par += nVar_Consv_Par;
20505 
20506  Variable_Names.push_back("Density");
20507  Variable_Names.push_back("X-Momentum");
20508  Variable_Names.push_back("Y-Momentum");
20509  if (geometry->GetnDim() == 3) Variable_Names.push_back("Z-Momentum");
20510  Variable_Names.push_back("Energy");
20511 
20512  /*--- Eventually, turbulence model from second container goes here. ---*/
20513 
20514 
20515  /*--- Add Pressure, Temperature, Cp, Mach. ---*/
20516 
20517  nVar_Par += 1;
20518  Variable_Names.push_back("Pressure");
20519 
20520  nVar_Par += 3;
20521  Variable_Names.push_back("Temperature");
20522  if (config->GetTabular_FileFormat() == TAB_CSV){
20523  Variable_Names.push_back("Pressure_Coefficient");
20524  } else {
20525  Variable_Names.push_back("C<sub>p</sub>");
20526  }
20527  Variable_Names.push_back("Mach");
20528 
20529  if ((Kind_Solver == FEM_NAVIER_STOKES) || (Kind_Solver == FEM_LES)){
20530  nVar_Par += 1;
20531  Variable_Names.push_back("Laminar_Viscosity");
20532  }
20533  if ((Kind_Solver == FEM_LES) && (config->GetKind_SGS_Model() != IMPLICIT_LES)){
20534  nVar_Par += 1;
20535  Variable_Names.push_back("Eddy_Viscosity");
20536  }
20537 
20538  if (solver[FLOW_SOL]->VerificationSolution) {
20539  if (solver[FLOW_SOL]->VerificationSolution->ExactSolutionKnown()) {
20540  nVar_Par += 2*nVar_Consv_Par;
20541  Variable_Names.push_back("Verification_Density");
20542  Variable_Names.push_back("Verification_Momentum_x");
20543  Variable_Names.push_back("Verification_Momentum_y");
20544  if (geometry->GetnDim() == 3) Variable_Names.push_back("Verification_Momentum_z");
20545  Variable_Names.push_back("Verification_Energy");
20546  Variable_Names.push_back("Error_Density");
20547  Variable_Names.push_back("Error_Momentum_x");
20548  Variable_Names.push_back("Error_Momentum_y");
20549  if (geometry->GetnDim() == 3) Variable_Names.push_back("Error_Momentum_z");
20550  Variable_Names.push_back("Error_Energy");
20551  }
20552  }
20553 
20554  /*--- New variables get registered here before the end of the loop. ---*/
20555 
20556 
20557  /*--- Create an object of the class CMeshFEM_DG and retrieve the necessary
20558  geometrical information for the FEM DG solver. ---*/
20559 
20560  CMeshFEM_DG *DGGeometry = dynamic_cast<CMeshFEM_DG *>(geometry);
20561 
20562  unsigned long nVolElemOwned = DGGeometry->GetNVolElemOwned();
20563  CVolumeElementFEM *volElem = DGGeometry->GetVolElem();
20564 
20565  /*--- Get a pointer to the fluid model class from the DG-FEM solver
20566  so that we can access the states below. ---*/
20567 
20568  CFluidModel *DGFluidModel = solver[FLOW_SOL]->GetFluidModel();
20569 
20570  /*--- Allocate the local data structure now that we know how many
20571  variables are in the output. ---*/
20572 
20573  Local_Data = new su2double*[nLocalPoint_Sort];
20574  for (iPoint = 0; iPoint < nLocalPoint_Sort; iPoint++) {
20575  Local_Data[iPoint] = new su2double[nVar_Par];
20576  }
20577 
20578  /*--------------------------------------------------------------------------*/
20579  /*--- Step 2: Loop over all grid nodes and load up the desired data for ---*/
20580  /*--- the restart and vizualization files. Note that we need to ---*/
20581  /*--- increment the iVar variable after each variable load. ---*/
20582  /*--- The idea is that we're filling up the columns of field ---*/
20583  /*--- data for each iPoint (row) of the data structure. ---*/
20584  /*--- This data will then be sorted, communicated, and written ---*/
20585  /*--- to files automatically after this routine. Note that the ---*/
20586  /*--- ordering of the data loading MUST match the order of the ---*/
20587  /*--- variable registration above for the files to be correct. ---*/
20588  /*--------------------------------------------------------------------------*/
20589 
20590  jPoint = 0;
20591 
20592  /*--- Access the solution by looping over the owned volume elements. ---*/
20593 
20594  for(unsigned long l=0; l<nVolElemOwned; ++l) {
20595 
20596  /* Set the pointers for the solution for this element. */
20597 
20598  const unsigned long offset = nVar_First*volElem[l].offsetDOFsSolLocal;
20599  su2double *solDOFs = solver[FirstIndex]->GetVecSolDOFs() + offset;
20600 
20601  for(unsigned short j=0; j<volElem[l].nDOFsSol; ++j) {
20602 
20603  /*--- Restart the column index with each new point. ---*/
20604 
20605  iVar = 0;
20606 
20607  /*--- Get the conservative variables for this particular DOF. ---*/
20608 
20609  const su2double *U = solDOFs + j*nVar_First;
20610 
20611  /*--- Load the coordinate values of the solution DOFs. ---*/
20612 
20613  const su2double *coor = volElem[l].coorSolDOFs.data() + j*nDim;
20614  for(unsigned short k=0; k<nDim; ++k) {
20615  Local_Data[jPoint][iVar] = coor[k];
20616  iVar++;
20617  }
20618 
20619  /* Load the conservative variables. */
20620 
20621  for(jVar=0; jVar < nVar_First; ++jVar) {
20622  Local_Data[jPoint][iVar] = U[jVar];
20623  iVar++;
20624  }
20625 
20626  /*--- Prepare the primitive states. ---*/
20627 
20628  const su2double DensityInv = 1.0/U[0];
20629  su2double vel[3], Velocity2 = 0.0;
20630  for(iDim=0; iDim<nDim; ++iDim) {
20631  vel[iDim] = U[iDim+1]*DensityInv;
20632  Velocity2 += vel[iDim]*vel[iDim];
20633  }
20634  su2double StaticEnergy = U[nDim+1]*DensityInv - 0.5*Velocity2;
20635  DGFluidModel->SetTDState_rhoe(U[0], StaticEnergy);
20636 
20637  /*--- Load data for the pressure, temperature, Cp, and Mach variables. ---*/
20638 
20639  Local_Data[jPoint][iVar] = DGFluidModel->GetPressure(); iVar++;
20640  Local_Data[jPoint][iVar] = DGFluidModel->GetTemperature(); iVar++;
20641  Local_Data[jPoint][iVar] = DGFluidModel->GetCp(); iVar++;
20642  Local_Data[jPoint][iVar] = sqrt(Velocity2)/DGFluidModel->GetSoundSpeed(); iVar++;
20643 
20644  if ((Kind_Solver == FEM_NAVIER_STOKES) || (Kind_Solver == FEM_LES)){
20645  Local_Data[jPoint][iVar] = DGFluidModel->GetLaminarViscosity(); iVar++;
20646  }
20647  if ((Kind_Solver == FEM_LES) && (config->GetKind_SGS_Model() != IMPLICIT_LES)){
20648  // todo: Export Eddy instead of Laminar viscosity
20649  Local_Data[jPoint][iVar] = DGFluidModel->GetLaminarViscosity(); iVar++;
20650  }
20651 
20652  if (solver[FLOW_SOL]->VerificationSolution) {
20653  if (solver[FLOW_SOL]->VerificationSolution->ExactSolutionKnown()) {
20654 
20655  /*--- Get the physical time if necessary. ---*/
20656  su2double time = 0.0;
20657  if (config->GetTime_Marching()) time = config->GetPhysicalTime();
20658 
20659  /* Get the verification solution. */
20660  su2double mmsSol[5];
20661  solver[FLOW_SOL]->VerificationSolution->GetSolution(coor, time, mmsSol);
20662  for (jVar = 0; jVar < nVar_First; jVar++) {
20663  Local_Data[jPoint][iVar] = mmsSol[jVar];
20664  iVar++;
20665  }
20666 
20667  /* Get local error from the verification solution class. */
20668  su2double error[5];
20669  solver[FLOW_SOL]->VerificationSolution->GetLocalError(coor, time, U, error);
20670  for (jVar = 0; jVar < nVar_First; jVar++) {
20671  Local_Data[jPoint][iVar] = error[jVar];
20672  iVar++;
20673  }
20674  }
20675  }
20676 
20677  /*--- New variables can be loaded to the Local_Data structure here,
20678  assuming they were registered above correctly. ---*/
20679 
20680  }
20681 
20682  /*--- Increment the point counter. ---*/
20683 
20684  jPoint++;
20685  }
20686 
20687 
20688 }
20689 
20691 
20692  unsigned long iPoint;
20693 
20694  /*--- Bool to distinguish between the FVM and FEM solvers. ---*/
20695 
20696  unsigned short KindSolver = config->GetKind_Solver();
20697  bool fem_solver = ((KindSolver == FEM_EULER) ||
20698  (KindSolver == FEM_NAVIER_STOKES) ||
20699  (KindSolver == FEM_RANS) ||
20700  (KindSolver == FEM_LES));
20701 
20702  /*--- Reset point sorting counters ---*/
20703 
20704  nGlobalPoint_Sort = 0;
20705  nLocalPoint_Sort = 0;
20706 
20707  /*--- Prepare the offsets for the FV solver ---*/
20708 
20709  if (!fem_solver) {
20710 
20711  /*--- Search all send/recv boundaries on this partition for any periodic
20712  nodes that were part of the original domain. We want to recover these
20713  for visualization purposes. ---*/
20714 
20715  unsigned long iVertex;
20716  bool isPeriodic;
20717 
20718  Local_Halo_Sort = new int[geometry->GetnPoint()];
20719  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
20720  Local_Halo_Sort[iPoint] = !geometry->node[iPoint]->GetDomain();
20721 
20722  for (unsigned short iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
20723  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
20724 
20725  /*--- Checking for less than or equal to the rank, because there may
20726  be some periodic halo nodes that send info to the same rank. ---*/
20727 
20728  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
20729  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
20730  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
20731  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1));
20732  if (isPeriodic) Local_Halo_Sort[iPoint] = false;
20733  }
20734  }
20735  }
20736 
20737  /*--- Sum total number of nodes that belong to the domain ---*/
20738 
20739  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
20740  if (Local_Halo_Sort[iPoint] == false)
20741  nLocalPoint_Sort++;
20742 
20743 #ifdef HAVE_MPI
20744  SU2_MPI::Allreduce(&nLocalPoint_Sort, &nGlobalPoint_Sort, 1,
20746 #else
20747  nGlobalPoint_Sort = nLocalPoint_Sort;
20748 #endif
20749 
20750  /*--- Set a final variable for the number of points in the restart
20751  file. We do not write the periodic points for the FV solver, even if
20752  they show up in the viz. files. ---*/
20753 
20754  nPoint_Restart = geometry->GetGlobal_nPointDomain();
20755 
20756  } else {
20757 
20758  /*--- Create an object of the class CMeshFEM_DG and retrieve the necessary
20759  geometrical information for the FEM DG solver. ---*/
20760 
20761  CMeshFEM_DG *DGGeometry = dynamic_cast<CMeshFEM_DG *>(geometry);
20762 
20763  unsigned long nVolElemOwned = DGGeometry->GetNVolElemOwned();
20764  CVolumeElementFEM *volElem = DGGeometry->GetVolElem();
20765 
20766  /*--- Update the solution by looping over the owned volume elements. ---*/
20767 
20768  for(unsigned long l=0; l<nVolElemOwned; ++l) {
20769 
20770  /* Count up the number of local points we have for allocating storage. */
20771 
20772  for(unsigned short j=0; j<volElem[l].nDOFsSol; ++j) {
20773  nLocalPoint_Sort++;
20774  }
20775  }
20776 
20777  Local_Halo_Sort = new int[nLocalPoint_Sort];
20778  for (iPoint = 0; iPoint < nLocalPoint_Sort; iPoint++)
20779  Local_Halo_Sort[iPoint] = false;
20780 
20781 #ifdef HAVE_MPI
20782  SU2_MPI::Allreduce(&nLocalPoint_Sort, &nGlobalPoint_Sort, 1,
20784 #else
20785  nGlobalPoint_Sort = nLocalPoint_Sort;
20786 #endif
20787 
20788  /*--- Set a final variable for the number of points in the restart
20789  file. We do not write the periodic points for the FV solver, even if
20790  they show up in the viz. files. ---*/
20791 
20792  nPoint_Restart = nGlobalPoint_Sort;
20793 
20794  }
20795 
20796  /*--- Now that we know the actual number of points we need to output,
20797  compute the number of points that will be on each processor.
20798  This is a linear partitioning with the addition of a simple load
20799  balancing for any remainder points. ---*/
20800 
20801  beg_node = new unsigned long[size];
20802  end_node = new unsigned long[size];
20803 
20804  nPointLinear = new unsigned long[size];
20805  nPointCumulative = new unsigned long[size+1];
20806 
20807  unsigned long total_points = 0;
20808  for (int ii = 0; ii < size; ii++) {
20809  nPointLinear[ii] = nGlobalPoint_Sort/size;
20810  total_points += nPointLinear[ii];
20811  }
20812 
20813  /*--- Get the number of remainder points after the even division. ---*/
20814 
20815  unsigned long remainder = nGlobalPoint_Sort - total_points;
20816  for (unsigned long ii = 0; ii < remainder; ii++) {
20817  nPointLinear[ii]++;
20818  }
20819 
20820  /*--- Store the local number of nodes on each proc in the linear
20821  partitioning, the beginning/end index, and the linear partitioning
20822  within an array in cumulative storage format. ---*/
20823 
20824  beg_node[0] = 0;
20825  end_node[0] = beg_node[0] + nPointLinear[0];
20826  nPointCumulative[0] = 0;
20827  for (int ii = 1; ii < size; ii++) {
20828  beg_node[ii] = end_node[ii-1];
20829  end_node[ii] = beg_node[ii] + nPointLinear[ii];
20830  nPointCumulative[ii] = nPointCumulative[ii-1] + nPointLinear[ii-1];
20831  }
20832  nPointCumulative[size] = nGlobalPoint_Sort;
20833 
20834 }
20835 
20836 void COutputLegacy::SortConnectivity_FEM(CConfig *config, CGeometry *geometry, unsigned short val_iZone) {
20837 
20838  /*--- Flags identifying the types of files to be written. ---*/
20839 
20840  bool Wrt_Vol = config->GetWrt_Vol_Sol();
20841  bool Wrt_Srf = config->GetWrt_Srf_Sol();
20842 
20843  /*--- Sort connectivity for each type of element (excluding halos). Note
20844  In these routines, we sort the connectivity into a linear partitioning
20845  across all processors based on the global index of the grid nodes. ---*/
20846 
20847  /*--- Sort volumetric grid connectivity. ---*/
20848 
20849  if (Wrt_Vol) {
20850 
20851  if ((rank == MASTER_NODE) && (size != SINGLE_NODE))
20852  cout <<"Sorting volumetric grid connectivity." << endl;
20853 
20854  SortVolumetricConnectivity_FEM(config, geometry, TRIANGLE );
20855  SortVolumetricConnectivity_FEM(config, geometry, QUADRILATERAL);
20856  SortVolumetricConnectivity_FEM(config, geometry, TETRAHEDRON );
20857  SortVolumetricConnectivity_FEM(config, geometry, HEXAHEDRON );
20858  SortVolumetricConnectivity_FEM(config, geometry, PRISM );
20859  SortVolumetricConnectivity_FEM(config, geometry, PYRAMID );
20860 
20861  }
20862 
20863  /*--- Sort surface grid connectivity. ---*/
20864 
20865  if (Wrt_Srf) {
20866 
20867  if ((rank == MASTER_NODE) && (size != SINGLE_NODE))
20868  cout <<"Sorting surface grid connectivity." << endl;
20869 
20870  SortSurfaceConnectivity_FEM(config, geometry, LINE );
20871  SortSurfaceConnectivity_FEM(config, geometry, TRIANGLE );
20872  SortSurfaceConnectivity_FEM(config, geometry, QUADRILATERAL);
20873 
20874  }
20875 
20876  /*--- Reduce the total number of cells we will be writing in the output files. ---*/
20877 
20878  unsigned long nTotal_Elem = nParallel_Tria + nParallel_Quad + nParallel_Tetr + nParallel_Hexa + nParallel_Pris + nParallel_Pyra;
20879  unsigned long nTotal_Surf_Elem = nParallel_Line + nParallel_BoundTria + nParallel_BoundQuad;
20880 #ifndef HAVE_MPI
20881  nGlobal_Elem_Par = nTotal_Elem;
20882  nSurf_Elem_Par = nTotal_Surf_Elem;
20883 #else
20884  SU2_MPI::Allreduce(&nTotal_Elem, &nGlobal_Elem_Par, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD);
20885  SU2_MPI::Allreduce(&nTotal_Surf_Elem, &nSurf_Elem_Par, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD);
20886 #endif
20887 
20888 }
20889 
20890 void COutputLegacy::SortVolumetricConnectivity_FEM(CConfig *config, CGeometry *geometry, unsigned short Elem_Type) {
20891 
20892  /* Determine the number of nodes for this element type. */
20893  unsigned short NODES_PER_ELEMENT = 0;
20894  switch (Elem_Type) {
20895  case TRIANGLE:
20896  NODES_PER_ELEMENT = N_POINTS_TRIANGLE;
20897  break;
20898  case QUADRILATERAL:
20899  NODES_PER_ELEMENT = N_POINTS_QUADRILATERAL;
20900  break;
20901  case TETRAHEDRON:
20902  NODES_PER_ELEMENT = N_POINTS_TETRAHEDRON;
20903  break;
20904  case HEXAHEDRON:
20905  NODES_PER_ELEMENT = N_POINTS_HEXAHEDRON;
20906  break;
20907  case PRISM:
20908  NODES_PER_ELEMENT = N_POINTS_PRISM;
20909  break;
20910  case PYRAMID:
20911  NODES_PER_ELEMENT = N_POINTS_PYRAMID;
20912  break;
20913  default:
20914  SU2_MPI::Error("Unrecognized element type", CURRENT_FUNCTION);
20915  }
20916 
20917  /*--- Create an object of the class CMeshFEM_DG and retrieve the necessary
20918  geometrical information for the FEM DG solver. ---*/
20919  CMeshFEM_DG *DGGeometry = dynamic_cast<CMeshFEM_DG *>(geometry);
20920 
20921  unsigned long nVolElemOwned = DGGeometry->GetNVolElemOwned();
20922  CVolumeElementFEM *volElem = DGGeometry->GetVolElem();
20923 
20924  const CFEMStandardElement *standardElementsSol = DGGeometry->GetStandardElementsSol();
20925 
20926  /*--- Determine the number of sub-elements on this rank. ---*/
20927  unsigned long nSubElem_Local = 0;
20928  for(unsigned long i=0; i<nVolElemOwned; ++i) {
20929 
20930  /* Determine the necessary data from the corresponding standard elem. */
20931  const unsigned short ind = volElem[i].indStandardElement;
20932  const unsigned short VTK_Type1 = standardElementsSol[ind].GetVTK_Type1();
20933  const unsigned short VTK_Type2 = standardElementsSol[ind].GetVTK_Type2();
20934 
20935  /* Only store the linear sub elements if they are of
20936  the current type that we are storing. */
20937  if(Elem_Type == VTK_Type1) nSubElem_Local += standardElementsSol[ind].GetNSubElemsType1();
20938  if(Elem_Type == VTK_Type2) nSubElem_Local += standardElementsSol[ind].GetNSubElemsType2();
20939  }
20940 
20941  /* Allocate the memory to store the connectivity if the size is
20942  larger than zero. */
20943  int *Conn_SubElem = NULL;
20944  if(nSubElem_Local > 0) Conn_SubElem = new int[nSubElem_Local*NODES_PER_ELEMENT];
20945 
20946  /*--- Loop again over the local volume elements and store the global
20947  connectivities of the sub-elements. Note one is added to the
20948  index value, because visualization softwares typically use
20949  1-based indexing. ---*/
20950  unsigned long kNode = 0;
20951  for(unsigned long i=0; i<nVolElemOwned; ++i) {
20952 
20953  /* Determine the necessary data from the corresponding standard elem. */
20954  const unsigned short ind = volElem[i].indStandardElement;
20955  const unsigned short VTK_Type1 = standardElementsSol[ind].GetVTK_Type1();
20956  const unsigned short VTK_Type2 = standardElementsSol[ind].GetVTK_Type2();
20957 
20958  /* Check if the first sub-element is of the required type. */
20959  if(Elem_Type == VTK_Type1) {
20960 
20961  /* Get the number of sub-elements and the local connectivity of
20962  the sub-elements. */
20963  const unsigned short nSubElems = standardElementsSol[ind].GetNSubElemsType1();
20964  const unsigned short *connSubElems = standardElementsSol[ind].GetSubConnType1();
20965 
20966  /* Store the global connectivities. */
20967  const unsigned short kk = NODES_PER_ELEMENT*nSubElems;
20968  for(unsigned short k=0; k<kk; ++k, ++kNode)
20969  Conn_SubElem[kNode] = connSubElems[k] + volElem[i].offsetDOFsSolGlobal + 1;
20970  }
20971 
20972  /* Check if the second sub-element is of the required type. */
20973  if(Elem_Type == VTK_Type2) {
20974 
20975  /* Get the number of sub-elements and the local connectivity of
20976  the sub-elements. */
20977  const unsigned short nSubElems = standardElementsSol[ind].GetNSubElemsType2();
20978  const unsigned short *connSubElems = standardElementsSol[ind].GetSubConnType2();
20979 
20980  /* Store the global connectivities. */
20981  const unsigned short kk = NODES_PER_ELEMENT*nSubElems;
20982  for(unsigned short k=0; k<kk; ++k, ++kNode)
20983  Conn_SubElem[kNode] = connSubElems[k] + volElem[i].offsetDOFsSolGlobal + 1;
20984  }
20985  }
20986 
20987  /*--- Store the particular global element count in the class data,
20988  and set the class data pointer to the connectivity array. ---*/
20989  switch (Elem_Type) {
20990  case TRIANGLE:
20991  nParallel_Tria = nSubElem_Local;
20992  Conn_Tria_Par = Conn_SubElem;
20993  break;
20994  case QUADRILATERAL:
20995  nParallel_Quad = nSubElem_Local;
20996  Conn_Quad_Par = Conn_SubElem;
20997  break;
20998  case TETRAHEDRON:
20999  nParallel_Tetr = nSubElem_Local;
21000  Conn_Tetr_Par = Conn_SubElem;
21001  break;
21002  case HEXAHEDRON:
21003  nParallel_Hexa = nSubElem_Local;
21004  Conn_Hexa_Par = Conn_SubElem;
21005  break;
21006  case PRISM:
21007  nParallel_Pris = nSubElem_Local;
21008  Conn_Pris_Par = Conn_SubElem;
21009  break;
21010  case PYRAMID:
21011  nParallel_Pyra = nSubElem_Local;
21012  Conn_Pyra_Par = Conn_SubElem;
21013  break;
21014  default:
21015  SU2_MPI::Error("Unrecognized element type", CURRENT_FUNCTION);
21016  break;
21017  }
21018 }
21019 
21020 void COutputLegacy::SortSurfaceConnectivity_FEM(CConfig *config, CGeometry *geometry, unsigned short Elem_Type) {
21021 
21022  /* Determine the number of nodes for this element type. */
21023  unsigned short NODES_PER_ELEMENT = 0;
21024  switch (Elem_Type) {
21025  case LINE:
21026  NODES_PER_ELEMENT = N_POINTS_LINE;
21027  break;
21028  case TRIANGLE:
21029  NODES_PER_ELEMENT = N_POINTS_TRIANGLE;
21030  break;
21031  case QUADRILATERAL:
21032  NODES_PER_ELEMENT = N_POINTS_QUADRILATERAL;
21033  break;
21034  default:
21035  SU2_MPI::Error("Unrecognized element type", CURRENT_FUNCTION);
21036  }
21037 
21038  /*--- Create an object of the class CMeshFEM_DG and retrieve the necessary
21039  geometrical information for the FEM DG solver. ---*/
21040  CMeshFEM_DG *DGGeometry = dynamic_cast<CMeshFEM_DG *>(geometry);
21041 
21042  unsigned long nVolElemOwned = DGGeometry->GetNVolElemOwned();
21043  CVolumeElementFEM *volElem = DGGeometry->GetVolElem();
21044 
21045  const CBoundaryFEM *boundaries = DGGeometry->GetBoundaries();
21046  const CFEMStandardBoundaryFace *standardBoundaryFacesSol = DGGeometry->GetStandardBoundaryFacesSol();
21047 
21048  /*--- Create the map from the global DOF ID to the local index.
21049  Note one is added to the index value, because visualization
21050  softwares typically use 1-based indexing. ---*/
21051  vector<unsigned long> globalID;
21052  for(unsigned long l=0; l<nVolElemOwned; ++l) {
21053  for(unsigned short j=0; j<volElem[l].nDOFsSol; ++j) {
21054  const unsigned long globalIndex = volElem[l].offsetDOFsSolGlobal + j + 1;
21055  globalID.push_back(globalIndex);
21056  }
21057  }
21058 
21059  /*--- Determine the number of sub-elements on this rank by looping
21060  over the surface elements of the boundary markers that must
21061  be plotted. ---*/
21062  unsigned long nSubElem_Local = 0;
21063  for(unsigned short iMarker=0; iMarker < config->GetnMarker_All(); ++iMarker) {
21064  if( !boundaries[iMarker].periodicBoundary ) {
21065  if (config->GetMarker_All_Plotting(iMarker) == YES) {
21066  const vector<CSurfaceElementFEM> &surfElem = boundaries[iMarker].surfElem;
21067  for(unsigned long i=0; i<surfElem.size(); ++i) {
21068  const unsigned short ind = surfElem[i].indStandardElement;
21069  const unsigned short VTK_Type = standardBoundaryFacesSol[ind].GetVTK_Type();
21070  if(Elem_Type == VTK_Type) nSubElem_Local += standardBoundaryFacesSol[ind].GetNSubFaces();
21071  }
21072  }
21073  }
21074  }
21075 
21076  /* Allocate the memory to store the connectivity if the size is
21077  larger than zero. */
21078  int *Conn_SubElem = NULL;
21079  if(nSubElem_Local > 0) Conn_SubElem = new int[nSubElem_Local*NODES_PER_ELEMENT];
21080 
21081  /*--- Repeat the loop over the surface elements of the boundary markers
21082  that must be plotted, but now store the connectivity. ---*/
21083  unsigned long kNode = 0;
21084  for(unsigned short iMarker=0; iMarker < config->GetnMarker_All(); ++iMarker) {
21085  if( !boundaries[iMarker].periodicBoundary ) {
21086  if (config->GetMarker_All_Plotting(iMarker) == YES) {
21087  const vector<CSurfaceElementFEM> &surfElem = boundaries[iMarker].surfElem;
21088 
21089  /* Loop over the surface elements of this boundary marker. */
21090  for(unsigned long i=0; i<surfElem.size(); ++i) {
21091 
21092  /* Check if this is the element type to be stored. */
21093  const unsigned short ind = surfElem[i].indStandardElement;
21094  const unsigned short VTK_Type = standardBoundaryFacesSol[ind].GetVTK_Type();
21095  if(Elem_Type == VTK_Type) {
21096 
21097  /* Get the number of sub-elements and the local connectivity of
21098  the sub-elements. */
21099  const unsigned short nSubFaces = standardBoundaryFacesSol[ind].GetNSubFaces();
21100  const unsigned short *connSubFaces = standardBoundaryFacesSol[ind].GetSubFaceConn();
21101 
21102  /* Store the global connectivities. */
21103  const unsigned short kk = NODES_PER_ELEMENT*nSubFaces;
21104  for(unsigned short k=0; k<kk; ++k, ++kNode)
21105  Conn_SubElem[kNode] = globalID[surfElem[i].DOFsSolFace[connSubFaces[k]]];
21106  }
21107  }
21108  }
21109  }
21110  }
21111 
21112  /*--- Store the particular global element count in the class data,
21113  and set the class data pointer to the connectivity array. ---*/
21114  switch (Elem_Type) {
21115  case LINE:
21116  nParallel_Line = nSubElem_Local;
21117  Conn_BoundLine_Par = Conn_SubElem;
21118  break;
21119  case TRIANGLE:
21120  nParallel_BoundTria = nSubElem_Local;
21121  Conn_BoundTria_Par = Conn_SubElem;
21122  break;
21123  case QUADRILATERAL:
21124  nParallel_BoundQuad = nSubElem_Local;
21125  Conn_BoundQuad_Par = Conn_SubElem;
21126  break;
21127  default:
21128  SU2_MPI::Error("Unrecognized element type", CURRENT_FUNCTION);
21129  break;
21130  }
21131 }
21132 
21134 
21135  unsigned long iProcessor;
21136  unsigned long iPoint, Global_Index;
21137 
21138  /* For convenience, set the total number of variables stored at each DOF. */
21139 
21140  int VARS_PER_POINT = nVar_Par;
21141 
21142 #ifdef HAVE_MPI
21143  SU2_MPI::Request *send_req, *recv_req;
21144  SU2_MPI::Status status;
21145  int ind;
21146 #endif
21147 
21148  /*--- Create an object of the class CMeshFEM_DG and retrieve the necessary
21149  geometrical information for the FEM DG solver. ---*/
21150 
21151  CMeshFEM_DG *DGGeometry = dynamic_cast<CMeshFEM_DG *>(geometry);
21152 
21153  unsigned long nVolElemOwned = DGGeometry->GetNVolElemOwned();
21154  CVolumeElementFEM *volElem = DGGeometry->GetVolElem();
21155 
21156  /*--- Create the map from the global DOF ID to the local index. ---*/
21157 
21158  //map<unsigned long, unsigned long> mapLocal2Global;
21159  vector<unsigned long> globalID;
21160 
21161  /*--- Update the solution by looping over the owned volume elements. ---*/
21162  for(unsigned long l=0; l<nVolElemOwned; ++l) {
21163 
21164  /* Loop over the DOFs for this element and store the solution. */
21165  for(unsigned short j=0; j<volElem[l].nDOFsSol; ++j) {
21166  const unsigned long globalIndex = volElem[l].offsetDOFsSolGlobal + j;
21167  globalID.push_back(globalIndex);
21168  }
21169  }
21170 
21171  /*--- We start with the grid nodes distributed across all procs with
21172  no particular ordering assumed. We need to loop through our local partition
21173  and decide how many nodes we must send to each other rank in order to
21174  have all nodes sorted according to a linear partitioning of the grid
21175  nodes, i.e., rank 0 holds the first ~ nGlobalPoint()/nProcessors nodes.
21176  First, initialize a counter and flag. ---*/
21177 
21178  int *nPoint_Send = new int[size+1]; nPoint_Send[0] = 0;
21179  int *nPoint_Recv = new int[size+1]; nPoint_Recv[0] = 0;
21180  int *nPoint_Flag = new int[size];
21181 
21182  for (int ii=0; ii < size; ii++) {
21183  nPoint_Send[ii] = 0;
21184  nPoint_Recv[ii] = 0;
21185  nPoint_Flag[ii]= -1;
21186  }
21187  nPoint_Send[size] = 0; nPoint_Recv[size] = 0;
21188 
21189  for (iPoint = 0; iPoint < nLocalPoint_Sort; iPoint++ ) {
21190 
21191  /*--- Get the global index of the current point. ---*/
21192 
21193  Global_Index = globalID[iPoint];
21194 
21195  /*--- Search for the processor that owns this point ---*/
21196 
21197  iProcessor = Global_Index/nPointLinear[0];
21198  if (iProcessor >= (unsigned long)size)
21199  iProcessor = (unsigned long)size-1;
21200  if (Global_Index >= nPointCumulative[iProcessor])
21201  while(Global_Index >= nPointCumulative[iProcessor+1]) iProcessor++;
21202  else
21203  while(Global_Index < nPointCumulative[iProcessor]) iProcessor--;
21204 
21205  /*--- If we have not visted this node yet, increment our
21206  number of elements that must be sent to a particular proc. ---*/
21207 
21208  if (nPoint_Flag[iProcessor] != (int)iPoint) {
21209  nPoint_Flag[iProcessor] = (int)iPoint;
21210  nPoint_Send[iProcessor+1]++;
21211  }
21212 
21213  }
21214 
21215  /*--- Communicate the number of nodes to be sent/recv'd amongst
21216  all processors. After this communication, each proc knows how
21217  many cells it will receive from each other processor. ---*/
21218 
21219 #ifdef HAVE_MPI
21220  SU2_MPI::Alltoall(&(nPoint_Send[1]), 1, MPI_INT,
21221  &(nPoint_Recv[1]), 1, MPI_INT, MPI_COMM_WORLD);
21222 #else
21223  nPoint_Recv[1] = nPoint_Send[1];
21224 #endif
21225 
21226  /*--- Prepare to send coordinates. First check how many
21227  messages we will be sending and receiving. Here we also put
21228  the counters into cumulative storage format to make the
21229  communications simpler. ---*/
21230 
21231  int nSends = 0, nRecvs = 0;
21232  for (int ii=0; ii < size; ii++) nPoint_Flag[ii] = -1;
21233 
21234  for (int ii = 0; ii < size; ii++) {
21235  if ((ii != rank) && (nPoint_Send[ii+1] > 0)) nSends++;
21236  if ((ii != rank) && (nPoint_Recv[ii+1] > 0)) nRecvs++;
21237 
21238  nPoint_Send[ii+1] += nPoint_Send[ii];
21239  nPoint_Recv[ii+1] += nPoint_Recv[ii];
21240  }
21241 
21242  /*--- Allocate memory to hold the connectivity that we are sending. ---*/
21243 
21244  su2double *connSend = NULL;
21245  connSend = new su2double[VARS_PER_POINT*nPoint_Send[size]];
21246  for (int ii = 0; ii < VARS_PER_POINT*nPoint_Send[size]; ii++)
21247  connSend[ii] = 0;
21248 
21249  /*--- Allocate arrays for sending the global ID. ---*/
21250 
21251  unsigned long *idSend = new unsigned long[nPoint_Send[size]];
21252  for (int ii = 0; ii < nPoint_Send[size]; ii++)
21253  idSend[ii] = 0;
21254 
21255  /*--- Create an index variable to keep track of our index
21256  positions as we load up the send buffer. ---*/
21257 
21258  unsigned long *index = new unsigned long[size];
21259  for (int ii=0; ii < size; ii++) index[ii] = VARS_PER_POINT*nPoint_Send[ii];
21260 
21261  unsigned long *idIndex = new unsigned long[size];
21262  for (int ii=0; ii < size; ii++) idIndex[ii] = nPoint_Send[ii];
21263 
21264  /*--- Loop through our elements and load the elems and their
21265  additional data that we will send to the other procs. ---*/
21266 
21267  for (iPoint = 0; iPoint < nLocalPoint_Sort; iPoint++) {
21268 
21269  /*--- Get the index of the current point. ---*/
21270 
21271  Global_Index = globalID[iPoint];
21272 
21273  /*--- Search for the processor that owns this point. ---*/
21274 
21275  iProcessor = Global_Index/nPointLinear[0];
21276  if (iProcessor >= (unsigned long)size)
21277  iProcessor = (unsigned long)size-1;
21278  if (Global_Index >= nPointCumulative[iProcessor])
21279  while(Global_Index >= nPointCumulative[iProcessor+1]) iProcessor++;
21280  else
21281  while(Global_Index < nPointCumulative[iProcessor]) iProcessor--;
21282 
21283  /*--- Load data into the buffer for sending. ---*/
21284 
21285  if (nPoint_Flag[iProcessor] != (int)iPoint) {
21286 
21287  nPoint_Flag[iProcessor] = (int)iPoint;
21288  unsigned long nn = index[iProcessor];
21289 
21290  /*--- Load the data values. ---*/
21291 
21292  for (unsigned short kk = 0; kk < VARS_PER_POINT; kk++) {
21293  connSend[nn] = Local_Data[iPoint][kk]; nn++;
21294  }
21295 
21296  /*--- Load the global ID (minus offset) for sorting the
21297  points once they all reach the correct processor. ---*/
21298 
21299  nn = idIndex[iProcessor];
21300  idSend[nn] = Global_Index - beg_node[iProcessor];
21301 
21302  /*--- Increment the index by the message length ---*/
21303 
21304  index[iProcessor] += VARS_PER_POINT;
21305  idIndex[iProcessor]++;
21306 
21307  }
21308 
21309  }
21310 
21311  /*--- Free memory after loading up the send buffer. ---*/
21312 
21313  delete [] index;
21314  delete [] idIndex;
21315 
21316  /*--- Allocate the memory that we need for receiving the conn
21317  values and then cue up the non-blocking receives. Note that
21318  we do not include our own rank in the communications. We will
21319  directly copy our own data later. ---*/
21320 
21321  su2double *connRecv = NULL;
21322  connRecv = new su2double[VARS_PER_POINT*nPoint_Recv[size]];
21323  for (int ii = 0; ii < VARS_PER_POINT*nPoint_Recv[size]; ii++)
21324  connRecv[ii] = 0;
21325 
21326  unsigned long *idRecv = new unsigned long[nPoint_Recv[size]];
21327  for (int ii = 0; ii < nPoint_Recv[size]; ii++)
21328  idRecv[ii] = 0;
21329 
21330 #ifdef HAVE_MPI
21331  /*--- We need double the number of messages to send both the conn.
21332  and the global IDs. ---*/
21333 
21334  send_req = new SU2_MPI::Request[2*nSends];
21335  recv_req = new SU2_MPI::Request[2*nRecvs];
21336 
21337  unsigned long iMessage = 0;
21338  for (int ii=0; ii<size; ii++) {
21339  if ((ii != rank) && (nPoint_Recv[ii+1] > nPoint_Recv[ii])) {
21340  int ll = VARS_PER_POINT*nPoint_Recv[ii];
21341  int kk = nPoint_Recv[ii+1] - nPoint_Recv[ii];
21342  int count = VARS_PER_POINT*kk;
21343  int source = ii;
21344  int tag = ii + 1;
21345  SU2_MPI::Irecv(&(connRecv[ll]), count, MPI_DOUBLE, source, tag,
21346  MPI_COMM_WORLD, &(recv_req[iMessage]));
21347  iMessage++;
21348  }
21349  }
21350 
21351  /*--- Launch the non-blocking sends of the connectivity. ---*/
21352 
21353  iMessage = 0;
21354  for (int ii=0; ii<size; ii++) {
21355  if ((ii != rank) && (nPoint_Send[ii+1] > nPoint_Send[ii])) {
21356  int ll = VARS_PER_POINT*nPoint_Send[ii];
21357  int kk = nPoint_Send[ii+1] - nPoint_Send[ii];
21358  int count = VARS_PER_POINT*kk;
21359  int dest = ii;
21360  int tag = rank + 1;
21361  SU2_MPI::Isend(&(connSend[ll]), count, MPI_DOUBLE, dest, tag,
21362  MPI_COMM_WORLD, &(send_req[iMessage]));
21363  iMessage++;
21364  }
21365  }
21366 
21367  /*--- Repeat the process to communicate the global IDs. ---*/
21368 
21369  iMessage = 0;
21370  for (int ii=0; ii<size; ii++) {
21371  if ((ii != rank) && (nPoint_Recv[ii+1] > nPoint_Recv[ii])) {
21372  int ll = nPoint_Recv[ii];
21373  int kk = nPoint_Recv[ii+1] - nPoint_Recv[ii];
21374  int count = kk;
21375  int source = ii;
21376  int tag = ii + 1;
21377  SU2_MPI::Irecv(&(idRecv[ll]), count, MPI_UNSIGNED_LONG, source, tag,
21378  MPI_COMM_WORLD, &(recv_req[iMessage+nRecvs]));
21379  iMessage++;
21380  }
21381  }
21382 
21383  /*--- Launch the non-blocking sends of the global IDs. ---*/
21384 
21385  iMessage = 0;
21386  for (int ii=0; ii<size; ii++) {
21387  if ((ii != rank) && (nPoint_Send[ii+1] > nPoint_Send[ii])) {
21388  int ll = nPoint_Send[ii];
21389  int kk = nPoint_Send[ii+1] - nPoint_Send[ii];
21390  int count = kk;
21391  int dest = ii;
21392  int tag = rank + 1;
21393  SU2_MPI::Isend(&(idSend[ll]), count, MPI_UNSIGNED_LONG, dest, tag,
21394  MPI_COMM_WORLD, &(send_req[iMessage+nSends]));
21395  iMessage++;
21396  }
21397  }
21398 #endif
21399 
21400  /*--- Copy my own rank's data into the recv buffer directly. ---*/
21401 
21402  int mm = VARS_PER_POINT*nPoint_Recv[rank];
21403  int ll = VARS_PER_POINT*nPoint_Send[rank];
21404  int kk = VARS_PER_POINT*nPoint_Send[rank+1];
21405 
21406  for (int nn=ll; nn<kk; nn++, mm++) connRecv[mm] = connSend[nn];
21407 
21408  mm = nPoint_Recv[rank];
21409  ll = nPoint_Send[rank];
21410  kk = nPoint_Send[rank+1];
21411 
21412  for (int nn=ll; nn<kk; nn++, mm++) idRecv[mm] = idSend[nn];
21413 
21414  /*--- Wait for the non-blocking sends and recvs to complete. ---*/
21415 
21416 #ifdef HAVE_MPI
21417  int number = 2*nSends;
21418  for (int ii = 0; ii < number; ii++)
21419  SU2_MPI::Waitany(number, send_req, &ind, &status);
21420 
21421  number = 2*nRecvs;
21422  for (int ii = 0; ii < number; ii++)
21423  SU2_MPI::Waitany(number, recv_req, &ind, &status);
21424 
21425  delete [] send_req;
21426  delete [] recv_req;
21427 #endif
21428 
21429  /*--- Store the connectivity for this rank in the proper data
21430  structure before post-processing below. First, allocate the
21431  appropriate amount of memory for this section. ---*/
21432 
21433  Parallel_Data = new su2double*[VARS_PER_POINT];
21434  for (int jj = 0; jj < VARS_PER_POINT; jj++) {
21435  Parallel_Data[jj] = new su2double[nPoint_Recv[size]];
21436  for (int ii = 0; ii < nPoint_Recv[size]; ii++) {
21437  Parallel_Data[jj][idRecv[ii]] = connRecv[ii*VARS_PER_POINT+jj];
21438  }
21439  }
21440 
21441  /*--- Store the total number of local points my rank has for
21442  the current section after completing the communications. ---*/
21443 
21444  nParallel_Poin = nPoint_Recv[size];
21445 
21446  /*--- Reduce the total number of points we will write in the output files. ---*/
21447 
21448 #ifndef HAVE_MPI
21449  nGlobal_Poin_Par = nParallel_Poin;
21450 #else
21451  SU2_MPI::Allreduce(&nParallel_Poin, &nGlobal_Poin_Par, 1,
21453 #endif
21454 
21455  /*--- Free temporary memory from communications ---*/
21456 
21457  delete [] connSend;
21458  delete [] connRecv;
21459  delete [] idSend;
21460  delete [] idRecv;
21461  delete [] nPoint_Recv;
21462  delete [] nPoint_Send;
21463  delete [] nPoint_Flag;
21464 
21465  for (iPoint = 0; iPoint < nLocalPoint_Sort; iPoint++)
21466  delete [] Local_Data[iPoint];
21467  delete [] Local_Data;
21468 
21469 }
21470 
21472 
21473  const int VARS_PER_POINT = nVar_Par;
21474 
21475  /*---------------------------------------------------*/
21476  /*--- Step 1: Determine the global DOF ID's of the */
21477  /*--- locally stored surface connectivities. */
21478  /*---------------------------------------------------*/
21479 
21480  /* Loop over the surface connectivities and store global
21481  DOF ID's in a vector. Subtract 1, because the stored
21482  connectivities are 1 based. */
21483  std::vector<unsigned long> globalSurfaceDOFIDs;
21484  globalSurfaceDOFIDs.reserve(nParallel_Line*N_POINTS_LINE +
21485  nParallel_BoundTria*N_POINTS_TRIANGLE +
21486  nParallel_BoundQuad*N_POINTS_QUADRILATERAL);
21487 
21488  for(unsigned long i=0; i<(nParallel_Line*N_POINTS_LINE); ++i) {
21489  const unsigned long globalID = Conn_BoundLine_Par[i]-1;
21490  globalSurfaceDOFIDs.push_back(globalID);
21491  }
21492 
21493  for(unsigned long i=0; i<(nParallel_BoundTria*N_POINTS_TRIANGLE); ++i) {
21494  const unsigned long globalID = Conn_BoundTria_Par[i]-1;
21495  globalSurfaceDOFIDs.push_back(globalID);
21496  }
21497 
21498  for(unsigned long i=0; i<(nParallel_BoundQuad*N_POINTS_QUADRILATERAL); ++i) {
21499  const unsigned long globalID = Conn_BoundQuad_Par[i]-1;
21500  globalSurfaceDOFIDs.push_back(globalID);
21501  }
21502 
21503  /* Sort globalSurfaceDOFIDs in increasing order and remove the
21504  multiple entries. */
21505  sort(globalSurfaceDOFIDs.begin(), globalSurfaceDOFIDs.end());
21506  vector<unsigned long>::iterator lastEntry;
21507  lastEntry = unique(globalSurfaceDOFIDs.begin(), globalSurfaceDOFIDs.end());
21508  globalSurfaceDOFIDs.erase(lastEntry, globalSurfaceDOFIDs.end());
21509 
21510  /*-------------------------------------------------------------------*/
21511  /*--- Step 2: Communicate the information of globalSurfaceDOFIDs ---*/
21512  /*--- to the ranks, which actually store this information ---*/
21513  /*--- in Parallel_Data. ---*/
21514  /*-------------------------------------------------------------------*/
21515 
21516  /* Allocate the memory for the first index of the communication buffers. */
21517  vector<vector<unsigned long> > sendBuf(size, vector<unsigned long>(0));
21518 
21519  /* Loop over the entries of globalSurfaceDOFIDs and fill the
21520  communication buffers accordingly. */
21521  for(unsigned long i=0; i<globalSurfaceDOFIDs.size(); ++i) {
21522 
21523  /* Search for the processor that owns this point. */
21524  unsigned long iProcessor = globalSurfaceDOFIDs[i]/nPointLinear[0];
21525  if (iProcessor >= (unsigned long)size)
21526  iProcessor = (unsigned long)size-1;
21527  if (globalSurfaceDOFIDs[i] >= nPointCumulative[iProcessor])
21528  while(globalSurfaceDOFIDs[i] >= nPointCumulative[iProcessor+1]) ++iProcessor;
21529  else
21530  while(globalSurfaceDOFIDs[i] < nPointCumulative[iProcessor]) --iProcessor;
21531 
21532  /* Store the global ID in the send buffer for iProcessor. */
21533  sendBuf[iProcessor].push_back(globalSurfaceDOFIDs[i]);
21534  }
21535 
21536  /* Determine the number of DOFs to be sent to each processor. */
21537  int nRankSend = 0;
21538  vector<unsigned long> nDOFSend(size);
21539  for(int i=0; i<size; ++i) {
21540  nDOFSend[i] = sendBuf[i].size();
21541  if(nDOFSend[i] && (i != rank)) ++nRankSend;
21542  }
21543 
21544  /* Communicate nDOFSend using Alltoall. */
21545  vector<unsigned long> nDOFRecv(size);
21546 
21547 #ifdef HAVE_MPI
21548  SU2_MPI::Alltoall(nDOFSend.data(), 1, MPI_UNSIGNED_LONG,
21549  nDOFRecv.data(), 1, MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
21550 #else
21551  nDOFRecv[rank] = nDOFSend[rank];
21552 #endif
21553 
21554  /* Determine the number of messages this rank will receive. */
21555  int nRankRecv = 0;
21556  for(int i=0; i<size; ++i) {
21557  if(nDOFRecv[i] && (i != rank)) ++nRankRecv;
21558  }
21559 
21560  /* Define the receive buffers. */
21561  vector<vector<unsigned long> > recvBuf(size, vector<unsigned long>(0));
21562 
21563 #ifdef HAVE_MPI
21564  /* Launch the non-blocking sends. Do not send anything to myself. */
21565  vector<SU2_MPI::Request> sendReq(nRankSend);
21566  nRankSend = 0;
21567  for(int i=0; i<size; ++i) {
21568  if(nDOFSend[i] && (i != rank)) {
21569  SU2_MPI::Isend(sendBuf[i].data(), nDOFSend[i], MPI_UNSIGNED_LONG,
21570  i, rank, MPI_COMM_WORLD, &sendReq[nRankSend]);
21571  ++nRankSend;
21572  }
21573  }
21574 
21575  /* Launch the non-blocking receives. Do not receive anything from myself. */
21576  vector<SU2_MPI::Request> recvReq(nRankRecv);
21577  nRankRecv = 0;
21578  for(int i=0; i<size; ++i) {
21579  if(nDOFRecv[i] && (i != rank)) {
21580  recvBuf[i].resize(nDOFRecv[i]);
21581  SU2_MPI::Irecv(recvBuf[i].data(), nDOFRecv[i], MPI_UNSIGNED_LONG,
21582  i, i, MPI_COMM_WORLD, &recvReq[nRankRecv]);
21583  ++nRankRecv;
21584  }
21585  }
21586 
21587 #endif
21588 
21589  /* Copy my own data. */
21590  recvBuf[rank] = sendBuf[rank];
21591 
21592 #ifdef HAVE_MPI
21593  /* Complete the non-blocking communication. */
21594  SU2_MPI::Waitall(nRankSend, sendReq.data(), MPI_STATUSES_IGNORE);
21595  SU2_MPI::Waitall(nRankRecv, recvReq.data(), MPI_STATUSES_IGNORE);
21596 #endif
21597 
21598  /*-------------------------------------------------------------------*/
21599  /*--- Step 2: Determine the number of locally stored surface DOFs ---*/
21600  /*--- and store the data in Parallel_Surf_Data. ---*/
21601  /*-------------------------------------------------------------------*/
21602 
21603  /* Store all received surface ID in one vector and sort it. */
21604  globalSurfaceDOFIDs.resize(0);
21605  for(int i=0; i<size; ++i) {
21606  if( nDOFRecv[i] )
21607  globalSurfaceDOFIDs.insert(globalSurfaceDOFIDs.end(),
21608  recvBuf[i].begin(), recvBuf[i].end());
21609  }
21610 
21611  sort(globalSurfaceDOFIDs.begin(), globalSurfaceDOFIDs.end());
21612  lastEntry = unique(globalSurfaceDOFIDs.begin(), globalSurfaceDOFIDs.end());
21613  globalSurfaceDOFIDs.erase(lastEntry, globalSurfaceDOFIDs.end());
21614 
21615  /* Allocate the memory for Parallel_Surf_Data. */
21616  nSurf_Poin_Par = globalSurfaceDOFIDs.size();
21617 
21618  Parallel_Surf_Data = new su2double*[VARS_PER_POINT];
21619  for(int jj=0; jj<VARS_PER_POINT; jj++)
21620  Parallel_Surf_Data[jj] = new su2double[nSurf_Poin_Par];
21621 
21622  /* Determine the local index of the global surface DOFs and
21623  copy the data into Parallel_Surf_Data. */
21624  for(unsigned long i=0; i<nSurf_Poin_Par; ++i) {
21625  const unsigned long ii = globalSurfaceDOFIDs[i] - nPointCumulative[rank];
21626 
21627  for(int jj=0; jj<VARS_PER_POINT; jj++)
21628  Parallel_Surf_Data[jj][i] = Parallel_Data[jj][ii];
21629  }
21630 
21631  /*--- Reduce the total number of surf points we have. This will be
21632  needed for writing the surface solution files later. ---*/
21633 #ifdef HAVE_MPI
21634  SU2_MPI::Allreduce(&nSurf_Poin_Par, &nGlobal_Surf_Poin, 1,
21636 #else
21637  nGlobal_Surf_Poin = nSurf_Poin_Par;
21638 #endif
21639 
21640  /*-------------------------------------------------------------------*/
21641  /*--- Step 3: Modify the surface connectivities, such that only ---*/
21642  /*--- the data of surface DOFs needs to be written. ---*/
21643  /*-------------------------------------------------------------------*/
21644 
21645  /* Determine the offset for my surface DOFs. */
21646  unsigned long offsetSurfaceDOFs = 0;
21647 #ifdef HAVE_MPI
21648  vector<unsigned long> nSurfaceDOFsRanks(size);
21649 
21650  SU2_MPI::Allgather(&nSurf_Poin_Par, 1, MPI_UNSIGNED_LONG,
21651  nSurfaceDOFsRanks.data(), 1, MPI_UNSIGNED_LONG,
21652  MPI_COMM_WORLD);
21653 
21654  for(int i=0; i<rank; ++i) offsetSurfaceDOFs += nSurfaceDOFsRanks[i];
21655 #endif
21656 
21657  /* Create the map from the global volume numbering to the new global
21658  surface numbering. */
21659  map<unsigned long, unsigned long> mapGlobalVol2Surf;
21660  for(unsigned long i=0; i<nSurf_Poin_Par; ++i)
21661  mapGlobalVol2Surf[globalSurfaceDOFIDs[i]] = offsetSurfaceDOFs + i;
21662 
21663  /* Fill the receive buffers with the modified global surface DOF numbers,
21664  such that this information can be returned to the original ranks. */
21665  for(int i=0; i<size; ++i) {
21666  for(unsigned long j=0; j<nDOFRecv[i]; ++j)
21667  recvBuf[i][j] = mapGlobalVol2Surf.find(recvBuf[i][j])->second;
21668  }
21669 
21670  /* Copy the original send buffers, because that information is
21671  still needed. */
21672  vector<vector<unsigned long> > originalSendBuf = sendBuf;
21673 
21674 #ifdef HAVE_MPI
21675  /* Launch the non-blocking sends for the reverse communication, where the
21676  receive buffers must be used for sending. Do not send anything to myself. */
21677  nRankRecv = 0;
21678  for(int i=0; i<size; ++i) {
21679  if(nDOFRecv[i] && (i != rank)) {
21680  SU2_MPI::Isend(recvBuf[i].data(), nDOFRecv[i], MPI_UNSIGNED_LONG,
21681  i, rank+1, MPI_COMM_WORLD, &recvReq[nRankRecv]);
21682  ++nRankRecv;
21683  }
21684  }
21685 
21686  /* Launch the non-blocking receives for the reverse communication, where the
21687  send buffers must be used for receiving. Do not receive anything from myself. */
21688  nRankSend = 0;
21689  for(int i=0; i<size; ++i) {
21690  if(nDOFSend[i] && (i != rank)) {
21691  SU2_MPI::Irecv(sendBuf[i].data(), nDOFSend[i], MPI_UNSIGNED_LONG,
21692  i, i+1, MPI_COMM_WORLD, &sendReq[nRankSend]);
21693  ++nRankSend;
21694  }
21695  }
21696 
21697 #endif
21698 
21699  /* Copy my own data. */
21700  sendBuf[rank] = recvBuf[rank];
21701 
21702 #ifdef HAVE_MPI
21703  /* Complete the non-blocking communication. */
21704  SU2_MPI::Waitall(nRankRecv, recvReq.data(), MPI_STATUSES_IGNORE);
21705  SU2_MPI::Waitall(nRankSend, sendReq.data(), MPI_STATUSES_IGNORE);
21706 #endif
21707 
21708  /* Clear the map mapGlobalVol2Surf and fill it with the data
21709  needed to modify the surface connectivity. Note that 1 is added,
21710  because the visualization softwares typically use 1 based indexing. */
21711  mapGlobalVol2Surf.clear();
21712 
21713  for(int i=0; i<size; ++i) {
21714  for(unsigned long j=0; j<nDOFSend[i]; ++j)
21715  mapGlobalVol2Surf[originalSendBuf[i][j]+1] = sendBuf[i][j]+1;
21716  }
21717 
21718  /* Modify the locally stored surface connectivities. */
21719  for(unsigned long i=0; i<(nParallel_Line*N_POINTS_LINE); ++i)
21720  Conn_BoundLine_Par[i] = mapGlobalVol2Surf.find(Conn_BoundLine_Par[i])->second;
21721 
21722  for(unsigned long i=0; i<(nParallel_BoundTria*N_POINTS_TRIANGLE); ++i)
21723  Conn_BoundTria_Par[i] = mapGlobalVol2Surf.find(Conn_BoundTria_Par[i])->second;
21724 
21725  for(unsigned long i=0; i<(nParallel_BoundQuad*N_POINTS_QUADRILATERAL); ++i)
21726  Conn_BoundQuad_Par[i] = mapGlobalVol2Surf.find(Conn_BoundQuad_Par[i])->second;
21727 }
virtual su2double GetSurface_CD(unsigned short val_marker)
A virtual member.
virtual su2double GetAllBound_CL_Inv(void)
A virtual member.
su2double * GetPoint_Max_Coord(unsigned short val_var)
Get the location of the maximal residual, this is useful for the convergence history.
void WriteTurboPerfConvHistory(CConfig *config)
Compute .
void SetiInst(unsigned short val_iInst)
Set the current instance.
const unsigned short N_POINTS_LINE
General output & CGNS defines.
const int HEAT_SOL
Position of the heat equation in the solution solver array.
virtual CFluidModel * GetFluidModel(void)
Compute the pressure at the infinity.
string GetBreakdown_FileName(void)
Get the name of the file with the forces breakdown of the problem.
unsigned short GetnMarker_Turbomachinery(void)
number Turbomachinery performance option specified from config file.
Running the SU2_DEF software.
su2double GetdCMx_dCL(void)
Value of the weight of the CD, CL, CM optimization.
su2double GetAoS_Offset(void)
Get the off set sideslip angle of the body. The solution and the geometry file are able to modifity t...
Non-dimensional compressible simulation with freestream pressure equal to 1.0.
virtual su2double GetCPressure(unsigned short val_marker, unsigned long val_vertex)
A virtual member.
void DeallocateConnectivity(CConfig *config, CGeometry *geometry, bool surf_sol)
Deallocate temporary memory needed for merging and writing connectivity.
void WriteCSV_Slice(CConfig *config, CGeometry *geometry, CSolver *FlowSolver, unsigned long iExtIter, unsigned short val_iZone, unsigned short val_direction)
Create and write a CSV file with a slice of data.
su2double GetSurface_MomentumDistortion(unsigned short val_imarker)
Get the momentum distortion at the surface.
void WriteRestart_Parallel_ASCII(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone, unsigned short val_iInst)
Write a native SU2 restart file (ASCII) in parallel.
Tecplot binary format for the solution output.
bool GetWrt_Vol_Sol(void)
Get information about writing a volume solution file.
virtual su2double GetCSkinFriction(unsigned short val_marker, unsigned long val_vertex, unsigned short val_dim)
A virtual member.
bool GetContinuous_Adjoint(void)
Determines if problem is adjoint.
su2double GetGas_ConstantND(void)
Get the value of specific gas constant.
void SetResult_Files(CSolver *****solver_container, CGeometry ****geometry, CConfig **config, unsigned long iExtIter, unsigned short val_nZone)
Writes and organizes the all the output files, except the history one, for serial computations...
bool GetBuffet_Monitoring(void)
Provides the buffet monitoring information.
unsigned short GetKind_ObjFunc(void)
Get the kind of objective function. There are several options: Drag coefficient, Lift coefficient...
static void Error(std::string ErrorMsg, std::string FunctionName)
su2double GetVelocity_Ref(void)
Get the value of the reference velocity for non-dimensionalization.
Objective function defined as the difference of a particular node respect to a reference position...
virtual su2double GetTotal_CFEA(void)
A virtual member.
string GetMesh_Out_FileName(void)
Get name of the output grid, this parameter is important for grid adaptation and deformation.
Definition of compressible solver.
virtual su2double GetAllBound_CSF_Mnt(void)
A virtual member.
CFEMStandardElement * GetStandardElementsSol(void)
Function, which makes available the standard volume elements of the solution.
su2double GetCoord(unsigned short val_dim)
Get the coordinates dor the control volume.
VTK nomenclature for defining a tetrahedron element.
virtual su2double GetAllBound_CFy_Mnt(void)
A virtual member.
Definition of a FEM solver.
su2double GetdCD_dCL(void)
Value of the weight of the CD, CL, CM optimization.
unsigned short GetnZone(void)
Get number of zones.
unsigned short indStandardElement
Index in the vector of standard elements.
Definition of the finite element Navier-Stokes&#39; solver.
Class which contains all the variables for the DG FEM solver.
unsigned short GetKind_ConductivityModel(void)
Get the value of the thermal conductivity model.
virtual void Evaluate_ObjFunc(CConfig *config)
Compute weighted-sum "combo" objective output.
bool GetInvDesign_Cp(void)
Information about computing and plotting the equivalent area distribution.
static void Gather(void *sendbuf, int sendcnt, Datatype sendtype, void *recvbuf, int recvcnt, Datatype recvtype, int root, Comm comm)
virtual su2double GetTotal_OFRefGeom(void)
A virtual member.
void SpecialOutput_SpanLoad(CSolver *solver, CGeometry *geometry, CConfig *config, bool output)
Writes forces at different sections.
virtual su2double GetGeometry_CrossTerm_Derivative(unsigned long iPoint, unsigned long iVar) const
A virtual member. Get the geometry solution.
Definition: CVariable.hpp:2113
int size
MPI Size.
bool GetGravityForce(void)
Get information about the gravity force.
unsigned short GetKind_Turb_Model(void)
Get the kind of the turbulence model.
virtual su2double GetTotal_OFRefNode(void)
A virtual member.
Definition of the continuous adjoint Reynolds-averaged Navier-Stokes&#39; (RANS) solver.
static void Waitany(int nrequests, Request *request, int *index, Status *status)
virtual su2double GetLimiter_Primitive(unsigned long iPoint, unsigned long iVar) const
A virtual member.
Definition: CVariable.hpp:1934
bool GetDomain(void)
For parallel computation, its indicates if a point must be computed or not.
virtual su2double GetAllBound_CFz_Inv(void)
A virtual member.
Kind of Turbulence model (Menter SST with sustaining terms for free-stream preservation).
const int ADJHEAT_SOL
Position of the adjoint heat equation in the solution solver array.
Definition of the incompressible Reynolds-averaged Navier-Stokes&#39; (RANS) solver.
const int TURB_SOL
Position of the turbulence model solution in the solver container array.
virtual su2double GetTotal_CoPx(void)
A virtual member.
void DeallocateData_Parallel(CConfig *config, CGeometry *geometry)
Deallocate temporary memory needed for merging and writing output data in parallel.
void LoadLocalData_Base(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone)
Load the desired solution data into a structure used for parallel reordering and output file writing ...
void SortVolumetricConnectivity_FEM(CConfig *config, CGeometry *geometry, unsigned short Elem_Type)
Sort the connectivity for a single volume element type into a linear partitioning across all processo...
double GetValue(const su2double &data)
Get the (primitive) value of the datatype (needs to be implemented for each new type).
unsigned short GetKind_Trans_Model(void)
Get the kind of the transition model.
virtual su2double GetCPressureTarget(unsigned short val_marker, unsigned long val_vertex)
A virtual member.
void SortOutputData_Surface_FEM(CConfig *config, CGeometry *geometry)
Sort the surface output data for each grid node into a linear partitioning across all processors (DG-...
virtual su2double GetSurface_CFx_Visc(unsigned short val_marker)
A virtual member.
bool GetWeakly_Coupled_Heat(void)
Get the heat equation.
virtual su2double GetTotal_Power(void)
A virtual member.
ScalarType * GetBlock(unsigned long val_ipoint)
Get the value of the residual.
Definition: CSysVector.cpp:421
unsigned short GetnMarker_TurboPerformance(void)
number Turbomachinery performance option specified from config file.
virtual su2double GetSoundSpeed(unsigned long iPoint) const
A virtual member.
Definition: CVariable.hpp:1234
const int FLOW_SOL
Position of the mean flow solution in the solver container array.
virtual su2double GetSurface_CMx_Visc(unsigned short val_marker)
A virtual member.
const unsigned short N_POINTS_TRIANGLE
General output & CGNS defines.
virtual su2double GetHeatFlux(unsigned short val_marker, unsigned long val_vertex)
A virtual member.
void SetSurface_Mach(unsigned short val_imarker, su2double val_surface_mach)
Set the mach number at the surface.
virtual su2double GetSurface_CFy_Mnt(unsigned short val_marker)
A virtual member.
void SetSurfaceCSV_Flow(CConfig *config, CGeometry *geometry, CSolver *FlowSolver, unsigned long iExtIter, unsigned short val_iZone, unsigned short val_iInst)
Create and write the file with the flow coefficient on the surface.
void MergeBaselineSolution_FEM(CConfig *config, CGeometry *geometry, CSolver *solver, unsigned short val_iZone)
Merge the solution into a data structure used for output file writing (DG-FEM).
Definition of the Navier-Stokes&#39; solver.
virtual su2double GetDensity(unsigned long iPoint) const
A virtual member.
Definition: CVariable.hpp:1139
su2double GetRes_RMS(unsigned short val_var)
Get the maximal residual, this is useful for the convergence history.
su2double GetAoS(void)
Get the angle of sideslip of the body. It relates to the rotation of the aircraft centerline from the...
CBaseMPIWrapper::Status * MPI_STATUS_IGNORE
unsigned short GetnMarker_All(void)
Get the total number of boundary markers including send/receive domains.
virtual su2double GetAllBound_CEff_Visc(void)
A virtual member.
Definition of the incompressible Navier-Stokes&#39; solver.
void SetSurface_Uniformity(unsigned short val_imarker, su2double val_surface_streamwiseuniformity)
Set the streamwise flow uniformity at the surface.
virtual su2double GetVelocity_Inf(unsigned short val_dim)
A virtual member.
virtual su2double GetAllBound_CFz_Mnt(void)
A virtual member.
Definition of linear elastic material.
virtual su2double GetSurface_CFx_Mnt(unsigned short val_marker)
A virtual member.
static int GetSize()
void SetCp_InverseDesign(CSolver *solver_container, CGeometry *geometry, CConfig *config, unsigned long iExtIter)
Writes inverse design.
bool GetInvDesign_HeatFlux(void)
Information about computing and plotting the equivalent area distribution.
No slip isothermal wall boundary condition.
su2double * GetGridVel(void)
Get the value of the grid velocity at the point.
virtual su2double GetRoe_Dissipation(unsigned long iPoint) const
A virtual member.
Definition: CVariable.hpp:361
virtual su2double GetTotal_IDC(void)
A virtual member.
su2double GetBulk_Modulus(void)
Get the value of the bulk modulus.
virtual su2double GetSolution_Vel(unsigned long iPoint, unsigned long iVar) const
Get the velocity (Structural Analysis).
Definition: CVariable.hpp:2266
virtual su2double GetSurface_CMz_Inv(unsigned short val_marker)
A virtual member.
void SetSurface_MassFlow(unsigned short val_imarker, su2double val_surface_massflow)
Set the massflow at the surface.
Paraview ASCII format for the solution output.
unsigned short GetNDOFsPerSubFace(void) const
Function, which makes available the number of DOFs of a linear subface, used for plotting, among others, plotting.
virtual su2double GetTotal_CMz(void)
A virtual member.
su2double GetFlowAngleIn_BC()
Get the inlet flow angle imposed as BC for internal flow.
virtual su2double GetEddyViscosity(unsigned long iPoint) const
A virtual member.
Definition: CVariable.hpp:1196
su2double GetSurface_TotalPressure(unsigned short val_imarker)
Get the total pressure at an outlet boundary.
void SpecialOutput_SonicBoom(CSolver *solver, CGeometry *geometry, CConfig *config, bool output)
Writes equivalent area.
virtual su2double GetAllBound_CFx_Mnt(void)
A virtual member.
virtual su2double GetYPlus(unsigned short val_marker, unsigned long val_vertex)
A virtual member.
virtual su2double GetAllBound_CMz_Mnt(void)
A virtual member.
long GetExtraHeatOutputZone(void)
Heat solver zone with extra screen output.
Tecplot format for the solution output.
su2double GetRestart_Bandwidth_Agg(void)
Set the sum of the bandwidth for writing binary restarts (to be averaged later).
CBoundaryFEM * GetBoundaries(void)
Function, which makes available the boundaries of the local FEM mesh.
void GetLocalError(const su2double *val_coords, const su2double val_t, const su2double *GetLocalErrorval_solution, su2double *val_error)
Get the local error defined as the local solution minus the verification solution.
virtual su2double GetGlobal_Sens_Nu(unsigned short iVal)
A virtual member.
Derivative with respect to the turb2lam.
virtual su2double GetTotal_NetThrust(void)
A virtual member.
unsigned long GetNVolElemOwned(void)
Function, which makes available the number of owned volume elements in the local FEM mesh...
void SpecialOutput_AnalyzeSurface(CSolver *solver, CGeometry *geometry, CConfig *config, bool output)
Writes one dimensional output.
bool GetRotating_Frame(void)
Get information about the rotational frame.
Kind of Turbulence model (Menter SST).
su2double GetTemperature()
Get fluid temperature.
Definition: fluid_model.inl:37
virtual su2double GetSurface_Buffet_Metric(unsigned short val_marker)
A virtual member.
bool GetAeroelastic_Simulation(void)
Get information about the aeroelastic simulation.
bool GetDynamic_Grid(void)
Get information about dynamic grids.
static void Comm_size(Comm comm, int *size)
Perfect Real gas model.
VTK nomenclature for defining a line element.
Definition of Neo-Hookean material.
su2double GetPressure()
Get fluid pressure.
Definition: fluid_model.inl:31
unsigned short GetKind_DensityModel(void)
Option to define the density model for incompressible flows.
su2double GetEA_IntLimit(unsigned short index)
Get the integration limits for the equivalent area computation.
unsigned short GetnMarker_ActDiskInlet(void)
Get the total number of boundary markers.
su2double GetStations_Bounds(unsigned short val_var)
Get the value of the limits for the sections.
const int SINGLE_NODE
There is only a node in the MPI parallelization.
static void Irecv(void *buf, int count, Datatype datatype, int source, int tag, Comm comm, Request *request)
unsigned short GetnMarker_Monitoring(void)
Get the total number of monitoring markers.
bool GetVisualize_Surface_Def(void)
Creates a teot file to visualize the surface deformation deformation made by the DEF software...
Ideal gas model.
virtual void SetTotal_CEquivArea(su2double val_cequivarea)
A virtual member.
Kind of Turbulent model (Spalart-Allmaras).
string GetMarker_TurboPerf_BoundOut(unsigned short index)
get outlet bounds name for Turbomachinery performance calculation.
void SetHeatFlux_InverseDesign(CSolver *solver_container, CGeometry *geometry, CConfig *config, unsigned long iExtIter)
Writes inverse design.
string GetMultizone_FileName(string val_filename, int val_iZone, string ext)
Append the zone index to the restart or the solution files.
void SortOutputData_FEM(CConfig *config, CGeometry *geometry)
Sort the output data for each grid node into a linear partitioning across all processors (DG-FEM solv...
string GetMarker_TurboPerf_BoundIn(unsigned short index)
get inlet bounds name for Turbomachinery performance calculation.
virtual su2double GetTotal_CQ(void)
A virtual member.
virtual su2double GetSensitivity(unsigned long iPoint, unsigned long iDim) const
Get the Sensitivity at the node.
Definition: CVariable.hpp:2721
virtual void SetTotal_CpDiff(su2double val_pressure)
A virtual member.
unsigned short GetKind_SGS_Model(void)
Get the kind of the subgrid scale model.
virtual void SetTotal_HeatFluxDiff(su2double val_heat)
A virtual member.
Derivative with respect to the freestream temperature.
string GetMultiInstance_FileName(string val_filename, int val_iInst, string ext)
Append the instance index to the restart or the solution files.
unsigned short GetKind_Regime(void)
Governing equations of the flow (it can be different from the run time equation). ...
Derivative with respect to the viscosity.
virtual su2double GetAllBound_CFx_Visc(void)
A virtual member.
unsigned short GetnMarker_EngineExhaust(void)
Get the total number of boundary markers.
void DeallocateCoordinates(CConfig *config, CGeometry *geometry)
Write the nodal coordinates and connectivity to a Tecplot binary mesh file.
virtual su2double GetAllBound_CMz_Visc(void)
A virtual member.
COutputLegacy(CConfig *congig)
Constructor of the class.
virtual void GetSolution(const su2double *val_coords, const su2double val_t, su2double *val_solution)
Get the exact solution at the current position and time.
virtual su2double GetTotal_MaxHeatFlux(void)
A virtual member.
virtual void SetTDState_rhoe(su2double rho, su2double e)
virtual member that would be different for each gas model implemented
Definition: fluid_model.inl:84
unsigned short GetNSubElemsType2(void) const
Function, which makes available the number of sub-elements of type 2 for plotting.
virtual unsigned long GetnElemTria()
A virtual member.
bool GetTime_Domain(void)
Check if the multizone problem is solved for time domain.
const unsigned int INST_0
Definition of the first instance per grid level.
su2double GetMin_Delta_Time(void)
Get the value of the minimum delta time.
Derivative with respect to the freestream pressure.
su2double GetInitial_BCThrust(void)
Get the value of the non-dimensionalized actuator disk turbulence intensity.
void LoadLocalData_FEM(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone)
Load the desired solution data into a structure used for parallel reordering and output file writing ...
virtual su2double GetAllBound_CFy_Inv(void)
A virtual member.
void SetSurface_IDC(unsigned short val_imarker, su2double val_surface_distortion)
Get the back pressure (static) at an outlet boundary.
unsigned short GetnLocationStations(void)
Get the number of sections.
Comma-separated values format for the solution output.
su2double GetSurface_TotalTemperature(unsigned short val_imarker)
Get the total temperature at an outlet boundary.
bool GetEquivArea(void)
Information about computing and plotting the equivalent area distribution.
virtual su2double GetVonMises_Stress(unsigned long iPoint) const
A virtual member.
Definition: CVariable.hpp:1756
virtual su2double GetTotal_CFy(void)
A virtual member.
virtual su2double GetSurface_CSF_Mnt(unsigned short val_marker)
A virtual member.
Constant thermal conductivity.
Van Der Waals gas model.
void LoadLocalData_Elasticity(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone)
Load the desired solution data into a structure used for parallel reordering and output file writing ...
bool GetWrt_Performance(void)
Get information about writing the performance summary at the end of a calculation.
su2double GetSurface_Uniformity(unsigned short val_imarker)
Get the streamwise flow uniformity at the surface.
unsigned long GetExtIter_OffSet(void)
Get the current internal iteration number.
void SetBaselineResult_Files_FEM(CSolver ***solver, CGeometry ***geometry, CConfig **config, unsigned long iExtIter, unsigned short val_nZone)
Writes and organizes the all the output files, except the history one, for DG-FEM simulations (SU2_SO...
virtual su2double GetTotal_CEff(void)
A virtual member.
void MergeCoordinates(CConfig *config, CGeometry *geometry)
Merge the node coordinates from all processors.
virtual su2double GetTotal_Custom_ObjFunc(void)
A virtual member.
virtual su2double GetSpecificHeatCp(unsigned long iPoint) const
A virtual member.
Definition: CVariable.hpp:1326
su2double GetPressure_ThermodynamicND(void)
Get the value of the non-dimensionalized thermodynamic pressure.
unsigned short nDOFsSol
Number of DOFs for the solution of the element.
virtual su2double GetTotal_AeroCD(void)
A virtual member.
unsigned short GetFinestMesh(void)
Get the index of the finest grid.
virtual unsigned long GetNode(unsigned short val_node)=0
A pure virtual member.
bool GetWrt_Csv_Sol(void)
Get information about writing a surface comma-separated values (CSV) solution file.
Class to store a volume element for the FEM solver.
Fuselage analysis.
virtual su2double GetSurface_CMx(unsigned short val_marker)
A virtual member.
unsigned long offsetDOFsSolGlobal
Global offset of the solution DOFs of this element.
void SetSurface_PressureDrop(unsigned short val_imarker, su2double val_surface_pressuredrop)
Set the pressure drop between two surfaces.
virtual su2double GetSurface_CMy(unsigned short val_marker)
A virtual member.
Definition of the finite element Euler&#39;s solver.
virtual su2double GetPressure_Inf(void)
A virtual member.
void SortOutputData(CConfig *config, CGeometry *geometry)
Sort the output data for each grid node into a linear partitioning across all processors.
Use a dual time stepping strategy for unsteady computations (2nd order).
void SpecialOutput_Distortion(CSolver *solver, CGeometry *geometry, CConfig *config, bool output)
Create and write the file with the flow coefficient on the surface.
virtual su2double GetSurface_CFy_Visc(unsigned short val_marker)
A virtual member.
virtual su2double GetSurface_CFy_Inv(unsigned short val_marker)
A virtual member.
su2double GetMach(void)
Get the value of the Mach number (velocity divided by speed of sound).
Derivative with respect to the reynolds number.
su2double GetSharpEdge_Distance(void)
Get the value of the distance to a sharp edge.
Definition of the discrete adjoint imcompressible Navier-Stokes&#39;.
virtual void SetTotal_ComboObj(su2double ComboObj)
Set the total "combo" objective (weighted sum of other values).
Tecplot format for the solution output.
virtual void SetTotal_DC60(su2double val_Total_DC60)
A virtual member.
virtual unsigned long GetnElemTetr()
A virtual member.
void WriteRestart_Parallel_Binary(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone, unsigned short val_iInst)
Write a native SU2 restart file (binary) in parallel.
void MergeSolution_FEM(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone)
Merge the FEM solution into a data structure used for output file writing.
virtual unsigned short GetVTK_Type(void)=0
A pure virtual member.
void LoadLocalData_Flow(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone)
Load the desired solution data into a structure used for parallel reordering and output file writing ...
su2double GetSurface_Pressure(unsigned short val_imarker)
Get the pressure at an outlet boundary.
virtual su2double GetTotal_HeatFlux(void)
A virtual member.
void SetConvHistory_Header(ofstream *ConvHist_file, CConfig *config, unsigned short val_iZone, unsigned short val_iInst)
Write the header of the history file.
void MergeBaselineSolution(CConfig *config, CGeometry *geometry, CSolver *solver, unsigned short val_iZone)
Merge the solution into a data structure used for output file writing.
unsigned short GetTime_Marching(void)
Provides information about the time integration, and change the write in the output files information...
Nacelle analysis.
virtual su2double GetTotal_Sens_Mach(void)
A virtual member.
su2double GetLocationStations(unsigned short val_section)
Get the airfoil sections in the slicing process.
virtual unsigned long GetnElemPris()
A virtual member.
void SetConvHistory_Body(ofstream *ConvHist_file, CGeometry ****geometry, CSolver *****solver_container, CConfig **config, CIntegration ****integration, bool DualTime, su2double timeused, unsigned short val_iZone, unsigned short val_iInst)
Write the history file and the convergence on the screen for serial computations. ...
int rank
MPI Rank.
su2double GetSurface_SecondaryStrength(unsigned short val_imarker)
Get the secondary flow strength at the surface.
Boundary send-receive definition.
su2double GetSensor(unsigned long iPoint) const
Get the pressure sensor.
Definition: CVariable.hpp:1054
const unsigned int MESH_0
Definition of the finest grid level.
Absolute criteria: abs(Res).
bool GetAxisymmetric(void)
Get information about the axisymmetric frame.
virtual su2double GetSurface_CL(unsigned short val_marker)
A virtual member.
No turbulence model.
virtual su2double GetSurface_CL_Mnt(unsigned short val_marker)
A virtual member.
Non-dimensional compressible simulation with freestream velocity equal to Mach number.
void SortSurfaceConnectivity_FEM(CConfig *config, CGeometry *geometry, unsigned short Elem_Type)
Sort the connectivity for a single surface element type into a linear partitioning across all process...
string GetConv_FileName(void)
Get the name of the file with the convergence history of the problem.
virtual su2double GetTotal_SolidCD(void)
A virtual member.
virtual su2double GetSurface_CSF(unsigned short val_marker)
A virtual member.
void GetNormal(su2double *val_normal)
Copy the the normal vector of a face.
unsigned short GetMarker_All_KindBC(unsigned short val_marker)
Get the kind of boundary for each marker.
Dimensional simulation (compressible or incompressible).
virtual su2double GetTotal_Sens_Temp(void)
Set the total farfield temperature sensitivity coefficient.
su2double GetDensity_Ref(void)
Get the value of the reference density for non-dimensionalization.
#define MPI_COMM_WORLD
unsigned short GetKind_SU2(void)
Get the kind of SU2 software component.
bool GetWrt_Limiters(void)
Get information about writing residuals to volume solution file.
virtual su2double GetSurface_CFx(unsigned short val_marker)
A virtual member.
virtual su2double GetTotal_CL(void)
A virtual member.
unsigned short GetnMarker_EngineInflow(void)
Get the total number of boundary markers.
virtual su2double GetSurface_CMy_Visc(unsigned short val_marker)
A virtual member.
su2double * GetVelocity_FreeStreamND(void)
Get the vector of the non-dimensionalized freestream velocity.
CVolumeElementFEM * GetVolElem(void)
Function, which makes available the volume elements in the local FEM mesh.
su2double GetPhysicalTime(void)
Get the current physical time.
CVertex *** vertex
Boundary Vertex vector (dual grid information).
virtual su2double GetSurface_CEff_Inv(unsigned short val_marker)
A virtual member.
bool GetFrozen_Visc_Cont(void)
Provides information about the way in which the turbulence will be treated by the cont...
VTK nomenclature for defining a hexahedron element.
virtual unsigned long GetnElemQuad()
A virtual member.
Kind of Turbulent model (Spalart-Allmaras Edwards).
const int ADJFEA_SOL
Position of the FEA adjoint equation in the solution solver array.
Definition of the discrete adjoint Reynolds-averaged Navier-Stokes&#39; (RANS) solver.
virtual su2double GetThermalConductivity(unsigned long iPoint) const
A virtual member.
Definition: CVariable.hpp:1319
CFEMStandardBoundaryFace * GetStandardBoundaryFacesSol(void)
Function, which makes available the standard boundary faces of the solution.
virtual unsigned long GetGlobal_nPointDomain()
A virtual member.
virtual su2double GetSurface_CFx_Inv(unsigned short val_marker)
A virtual member.
virtual su2double GetAllBound_CMz_Inv(void)
A virtual member.
const unsigned int MAX_STRING_SIZE
Maximum number of domains.
Definition of incompressible solver.
unsigned long GetnElem(void)
Get number of elements.
su2double GetMach_Motion(void)
Get the mach number based on the mesh velocity and freestream quantities.
void LoadLocalData_AdjFlow(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone)
Load the desired solution data into a structure used for parallel reordering and output file writing ...
const unsigned short N_POINTS_TETRAHEDRON
General output & CGNS defines.
Include contribution to effective conductivity using constant turbulent Prandtl number for RANS...
bool GetSpecial_Output(void)
Check if the special output is written.
Incompressible ideal gas model.
virtual void SetCPressureTarget(unsigned short val_marker, unsigned long val_vertex, su2double val_pressure)
A virtual member.
unsigned short GetTabular_FileFormat(void)
Get the format of the output solution.
su2double GetPressureOut_BC()
Get the outlet pressure imposed as BC for internal flow.
~COutputLegacy(void)
Destructor of the class.
virtual su2double GetTotal_Sens_Press(void)
Set the total farfield pressure sensitivity coefficient.
virtual su2double GetSurface_CD_Mnt(unsigned short val_marker)
A virtual member.
su2double * GetSpanWiseValue(unsigned short val_marker)
Get number of vertices.
const su2double PI_NUMBER
Pi number.
CVerificationSolution * VerificationSolution
Verification solution class used within the solver.
virtual su2double * GetStress_FEM(unsigned long iPoint)
A virtual member.
Definition: CVariable.hpp:1746
void SetResult_Files_Parallel(CSolver *****solver_container, CGeometry ****geometry, CConfig **config, unsigned long iExtIter, unsigned short val_nZone)
Writes and organizes the all the output files, except the history one, for parallel computations...
Mass-flux weighted average.
Non-dimensional incompressible simulation based on custom reference values.
Definition of the incompressible Euler&#39;s solver.
virtual su2double GetTemperature(unsigned long iPoint) const
A virtual member.
Definition: CVariable.hpp:1247
No turbulent contribution to the effective thermal conductivity for RANS.
void SpecialOutput_FSI(ofstream *FSIHist_file, CGeometry ****geometry, CSolver *****solver_container, CConfig **config, CIntegration ****integration, unsigned long iExtIter, unsigned short ZONE_FLOW, unsigned short ZONE_STRUCT, bool header)
Create and write the file with the FSI convergence history.
VTK nomenclature for defining a quadrilateral element.
Inc. ideal gas, polynomial gas model.
unsigned short GetNSubFaces(void) const
Function, which makes available the number of linear subfaces used for plotting, among others...
const int CGNS_STRING_SIZE
Length of strings used in the CGNS format.
virtual su2double GetAllBound_CMy_Mnt(void)
A virtual member.
Sensor for detecting separation.
virtual su2double GetSurface_CMy_Inv(unsigned short val_marker)
A virtual member.
bool GetWrt_Dynamic(void)
Get information about writing dynamic structural analysis headers and file extensions.
virtual su2double GetSurface_CMx_Mnt(unsigned short val_marker)
A virtual member.
Definition of the Reynolds-averaged Navier-Stokes&#39; (RANS) solver.
virtual unsigned long GetIter_Update_AoA()
A virtual member.
bool GetWrt_Surface(void)
Write solution at each surface.
virtual su2double GetTotal_Sens_ModVel(void)
A virtual member.
Implicit LES, i.e. no explicit SGS model.
virtual su2double GetTotal_Sens_BPress(void)
Get the total back pressure sensitivity coefficient.
const unsigned short N_POINTS_HEXAHEDRON
General output & CGNS defines.
void DeallocateSolution(CConfig *config, CGeometry *geometry)
Deallocate temporary memory needed for merging and writing solution variables.
string GetSurfCoeff_FileName(void)
Get the name of the file with the surface information for the flow problem.
Parent class for defining the geometry of the problem (complete geometry, multigrid agglomerated geom...
virtual su2double * GetVorticity(unsigned long iPoint)
A virtual member.
Definition: CVariable.hpp:1368
virtual su2double GetSurface_CFz_Visc(unsigned short val_marker)
A virtual member.
virtual su2double GetAllBound_CD_Inv(void)
A virtual member.
Relative criteria: Res/Res0.
void SetMesh_Files(CGeometry **geometry, CConfig **config, unsigned short val_nZone, bool new_file, bool su2_file)
Writes and organizes the all the output files, except the history one, for serial computations...
virtual su2double GetSurface_CMy_Mnt(unsigned short val_marker)
A virtual member.
Definition of the finite element Reynolds-averaged Navier-Stokes&#39; (RANS) solver.
void SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry ****geometry, CConfig **config, unsigned short val_iZone, bool output)
Write the history file and the convergence on the screen for serial computations. ...
const unsigned short * GetSubConnType2(void) const
Function, which makes available the the connectivity of the linear elements of type 2 as a const poin...
virtual su2double GetTotal_AvgTemperature(void)
A virtual member.
Kind of Turbulent model (Spalart-Allmaras Edwards with Compressibility Correction).
virtual su2double GetGammaBC(unsigned long iPoint) const
A virtual member.
Definition: CVariable.hpp:1403
Sutherlands Law viscosity.
su2double GetSolution_Old(unsigned long iPoint, unsigned long iVar) const
Get the old solution of the problem (Runge-Kutta method)
Definition: CVariable.hpp:224
Main class for doing the space integration, time integration, and monitoring of a system of Partial D...
Constant density gas model.
virtual void SetTotal_IDC(su2double val_Total_IDC)
A virtual member.
virtual su2double GetAllBound_CL_Visc(void)
A virtual member.
virtual su2double GetSurface_CL_Inv(unsigned short val_marker)
A virtual member.
string GetMarker_Monitoring_TagBound(unsigned short val_marker)
Get the name of the surface defined in the geometry file.
virtual su2double GetTotal_CFz(void)
A virtual member.
virtual su2double GetAllBound_CEff_Mnt(void)
A virtual member.
unsigned short GetNDOFsPerSubElem(unsigned short val_VTK_Type) const
Function, which makes available the number of DOFs of a linear element, used for plotting.
unsigned short GetKind_RoeLowDiss(void)
Get the Kind of Roe Low Dissipation Scheme for Unsteady flows.
codi::RealForward su2double
su2double GetPressure_FreeStreamND(void)
Get the value of the non-dimensionalized freestream pressure.
unsigned short GetDirectDiff()
Get the direct differentation method.
void SetSurface_TotalTemperature(unsigned short val_imarker, su2double val_surface_totaltemperature)
Set the total temperature at the surface.
void SetSurface_TotalPressure(unsigned short val_imarker, su2double val_surface_totalpressure)
Set the total pressure at the surface.
bool GetRestart(void)
Provides the restart information.
unsigned long * nVertex
Number of vertex for each marker.
void MergeConnectivity(CConfig *config, CGeometry *geometry, unsigned short val_iZone)
Merge the geometry into a data structure used for output file writing.
Standard air gas model.
void SetResult_Files_FEM(CSolver ****solver_container, CGeometry ***geometry, CConfig **config, unsigned long iExtIter, unsigned short val_nZone)
Writes and organizes the all the output files, except the history one, for serial computations with t...
void MergeSolution(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone)
Merge the solution into a data structure used for output file writing.
Derivative with respect to the angle of attack.
bool GetIncrementalLoad(void)
Check if we want to apply an incremental load to the nonlinear structural simulation.
CPoint ** node
Node vector (dual grid information).
#define MPI_DOUBLE
su2double GetSemiSpan(void)
Get the wing semi span.
void SetSurface_Pressure(unsigned short val_imarker, su2double val_surface_pressure)
Set the pressure at the surface.
unsigned long offsetDOFsSolLocal
Local offset of the solution DOFs of this element.
Domain interface definition.
unsigned long GetRestart_Iter(void)
Get the restart iteration.
#define MPI_UNSIGNED_SHORT
virtual su2double GetTotal_CNearFieldOF(void)
A virtual member.
Class to define a FEM standard element.
static void Alltoall(void *sendbuf, int sendcount, Datatype sendtype, void *recvbuf, int recvcount, Datatype recvtype, Comm comm)
unsigned long GetGlobalIndex(void)
Get the global index in a parallel computation.
su2double GetTemperature_FreeStreamND(void)
Get the value of the non-dimensionalized freestream temperature.
virtual su2double GetSensitivity(unsigned long iPoint, unsigned short iDim)
A virtual member.
unsigned long GetInnerIter(void)
Get the current FSI iteration number.
virtual unsigned long GetnElemPyra()
A virtual member.
su2double GetSolution(unsigned long iPoint, unsigned long iVar) const
Get the solution.
Definition: CVariable.hpp:216
virtual su2double GetSurface_CFz_Mnt(unsigned short val_marker)
A virtual member.
virtual su2double GetTotal_Buffet_Metric(void)
A virtual member.
unsigned short GetKind_Solver(void)
Governing equations of the flow (it can be different from the run time equation). ...
void SetSurface_MomentumDistortion(unsigned short val_imarker, su2double val_surface_momentumdistortion)
Set the momentum distortion at the surface.
su2double GetAoA_Offset(void)
Get the off set angle of attack of the body. The solution and the geometry file are able to modifity ...
const int FEA_SOL
Position of the FEA equation in the solution solver array.
virtual su2double GetTotal_CD(void)
A virtual member.
Class to define a FEM standard boundary face.
void SetSolution(unsigned long iPoint, const su2double *solution)
Set the value of the solution, all variables.
Definition: CVariable.hpp:166
Non-dimensional compressible simulation with freestream pressure equal to 1.0.
bool GetWrt_Halo(void)
Get information about writing rind layers to the solution files.
virtual su2double GetAllBound_CSF_Visc(void)
A virtual member.
su2double GetSurface_NormalVelocity(unsigned short val_imarker)
Get the normal velocity at an outlet boundary.
static unsigned short GetnZone(string val_mesh_filename, unsigned short val_format)
Gets the number of zones in the mesh file.
bool GetFixed_CL_Mode(void)
Get information about whether to use fixed CL mode.
virtual void SetTotal_IDR(su2double val_Total_IDR)
A virtual member.
void SetSurface_IDC_Mach(unsigned short val_imarker, su2double val_surface_distortion)
Get the back pressure (static) at an outlet boundary.
#define B(i, j)
Boolean definition of yes.
virtual su2double GetModVelocity_Inf(void)
A virtual member.
Definition of the discrete adjoint imcompressible Reynolds-averaged Navier-Stokes&#39; (RANS) solver...
double passivedouble
void SetSurface_Density(unsigned short val_imarker, su2double val_surface_density)
Set the density at the surface.
su2double GetdCMy_dCL(void)
Value of the weight of the CD, CL, CM optimization.
Upwind convective numerical method.
su2double GetTurb2LamViscRatio_FreeStream(void)
Get the value of the turbulent to laminar viscosity ratio.
vector< string > fields
Tags for the different fields in a restart file.
su2double GetSurface_Mach(unsigned short val_imarker)
Get the mach number at an outlet boundary.
unsigned long GetPoint_Max(unsigned short val_var)
Get the maximal residual, this is useful for the convergence history.
virtual su2double GetTotal_CMerit(void)
A virtual member.
#define MPI_MAX
CSysVector< su2double > LinSysRes
vector to store iterative residual of implicit linear system.
void SortVolumetricConnectivity(CConfig *config, CGeometry *geometry, unsigned short Elem_Type)
Sort the connectivity for a single volume element type into a linear partitioning across all processo...
const int ADJFLOW_SOL
Position of the continuous adjoint flow solution in the solver container array.
vector< CSurfaceElementFEM > surfElem
Vector of the local surface elements.
bool GetBoolTurbomachinery(void)
Verify if there is Turbomachinery performance option specified from config file.
virtual unsigned long GetnDOFsGlobal(void)
A virtual member.
unsigned long GetnElem_Bound(unsigned short val_marker)
Get the number of boundary elements.
Kind of Turbulent model (Spalart-Allmaras Compressibility Correction).
virtual su2double GetVelocity(unsigned long iPoint, unsigned long iDim) const
A virtual member.
Definition: CVariable.hpp:1276
virtual su2double GetSurface_CMx_Inv(unsigned short val_marker)
A virtual member.
su2double GetTemperature_Ref(void)
Get the value of the reference temperature for non-dimensionalization.
void DeallocateConnectivity_Parallel(CConfig *config, CGeometry *geometry, bool surf_sol)
Deallocate temporary memory needed for merging and writing connectivity in parallel.
unsigned short GetnMarker_Analyze(void)
Get the total number of moving markers.
unsigned short GetGeometricConditions(void)
Geometric conditions for the structural solver.
virtual su2double GetTotal_CMy(void)
A virtual member.
Boundary Euler wall definition.
int Int(const su2double &data)
Casts the primitive value to int (uses GetValue, already implemented for each type).
#define MPI_CHAR
unsigned short GetKind_ConvNumScheme(void)
Get the kind of convective numerical scheme.
void SortOutputData_Surface(CConfig *config, CGeometry *geometry)
Sort the surface output data for each grid node into a linear partitioning across all processors...
Definition of the finite volume heat solver.
Definition of the finite element Large Eddy Simulation Navier-Stokes&#39; (LES) solver.
unsigned short GetKind_FluidModel(void)
Fluid model that we are using.
unsigned short GetNSubElemsType1(void) const
Function, which makes available the number of sub-elements of type 1 for plotting.
Main class for defining a baseline solution from a restart file (for output).
CPrimalGrid ** elem
Element vector (primal grid information).
su2double GetSurface_IDC_Mach(unsigned short val_imarker)
Get the back pressure (static) at an outlet boundary.
unsigned long GetnPoint(void)
Get number of points.
Perform all MPI communications.
virtual su2double GetAllBound_CFy_Visc(void)
A virtual member.
virtual su2double GetSurface_CSF_Inv(unsigned short val_marker)
A virtual member.
unsigned short GetVTK_Type1(void) const
Function, which makes available the type of the element in subConn1ForPlotting.
Polynomial viscosity.
Main class for defining the problem; basically this class reads the configuration file...
vector< su2double > coorSolDOFs
The coordinates of the solution DOFs of this element.
static void Allgather(void *sendbuf, int sendcnt, Datatype sendtype, void *recvbuf, int recvcnt, Datatype recvtype, Comm comm)
void SetRestart_Bandwidth_Agg(su2double val_restart_bandwidth_sum)
Set the sum of the bandwidth for writing binary restarts (to be averaged later).
#define MPI_UNSIGNED_LONG
const unsigned short * GetSubFaceConn(void) const
Function, which makes available the the connectivity of the linear subfaces as a const pointer...
su2double * GetDistortionRack(void)
Get the distortion rack.
const unsigned int ZONE_0
Definition of the first grid domain.
void MergeSurfaceConnectivity_FEM(CConfig *config, CGeometry *geometry, unsigned short Elem_Type)
Merge the connectivity for a single element type from all processors for the FEM solver.
unsigned short GetiInst(void)
Get the current instance.
string GetMarker_All_TagBound(unsigned short val_marker)
Get the index of the surface defined in the geometry file.
su2double GetSurface_Temperature(unsigned short val_imarker)
Get the temperature at an outlet boundary.
const int ADJTURB_SOL
Position of the continuous adjoint turbulence solution in the solver container array.
bool GetEnergy_Equation(void)
Flag for whether to solve the energy equation for incompressible flows.
virtual su2double GetTotal_Sens_AoA(void)
A virtual member.
void SpecialOutput_Turbo(CSolver *****solver_container, CGeometry ****geometry, CConfig **config, unsigned short val_iZone, bool output)
Write the output file for spanwise turboperformance.
su2double GetSurface_DC60(unsigned short val_imarker)
Get the back pressure (static) at an outlet boundary.
void SetSensitivity_Files(CGeometry ***geometry, CConfig **config, unsigned short val_nZone)
Write the sensitivity (including mesh sensitivity) computed with the discrete adjoint method on the s...
BoussinesQ density model.
vector< su2double > Volume_Ratio
Measure of dual CV volume ratio (max sub-element volume / min sub-element volume).
bool GetDiscrete_Adjoint(void)
Get the indicator whether we are solving an discrete adjoint problem.
unsigned short GetnDim(void)
Get number of coordinates.
virtual su2double GetSurface_CEff_Mnt(unsigned short val_marker)
A virtual member.
virtual su2double GetGlobal_Sens_E(unsigned short iVal)
A virtual member.
virtual su2double GetAllBound_CD_Visc(void)
A virtual member.
void SetSurface_IDR(unsigned short val_imarker, su2double val_surface_distortion)
Get the back pressure (static) at an outlet boundary.
bool GetWrt_Srf_Sol(void)
Get information about writing a surface solution file.
void SetSpecial_Output(CSolver *****solver_container, CGeometry ****geometry, CConfig **config, unsigned long iExtIter, unsigned short val_nZone)
Writes the special output files.
Derivative with respect to the design??
Definition of compressible solver.
virtual su2double GetEnthalpy(unsigned long iPoint) const
A virtual member.
Definition: CVariable.hpp:1203
virtual su2double GetAllBound_CMy_Inv(void)
A virtual member.
bool GetWrt_SharpEdges(void)
Get information about writing residuals to volume solution file.
virtual su2double GetDES_LengthScale(unsigned long iPoint) const
A virtual member.
Definition: CVariable.hpp:387
su2double GetInc_Velocity_Ref(void)
Get the value of the reference velocity for custom incompressible non-dimensionalization.
Near-Field boundary definition.
virtual su2double GetAllBound_CD_Mnt(void)
A virtual member.
const unsigned short N_POINTS_PYRAMID
General output & CGNS defines.
void MergeVolumetricConnectivity_FEM(CConfig *config, CGeometry *geometry, unsigned short Elem_Type)
Merge the connectivity for a single element type from all processors for the FEM solver.
Definition of the continuous adjoint Navier-Stokes&#39; solver.
vector< su2double > Aspect_Ratio
Measure of dual CV aspect ratio (max face area / min face area).
Definition of the discrete adjoint Euler solver.
su2double GetGamma(void)
Get the value of the Gamma of fluid (ratio of specific heats).
virtual su2double GetAllBound_CEff_Inv(void)
A virtual member.
virtual su2double GetForceCoeff()
A virtual member.
unsigned short GetMarker_All_Plotting(unsigned short val_marker)
Get the plotting information for a marker val_marker.
void SetSurfaceCSV_Adjoint(CConfig *config, CGeometry *geometry, CSolver *AdjSolver, CSolver *FlowSolution, unsigned long iExtIter, unsigned short val_iZone, unsigned short val_iInst)
Create and write the file with the adjoint coefficients on the surface for serial computations...
Variable density model.
static int GetRank()
No Roe Low Dissipation model.
virtual su2double GetOmega_Max(void)
A virtual member.
CVariable * GetNodes()
Allow outside access to the nodes of the solver, containing conservatives, primitives, etc.
Space centered convective numerical method.
#define SPRINTF
virtual su2double GetSurface_CSF_Visc(unsigned short val_marker)
A virtual member.
void SetSurface_NormalVelocity(unsigned short val_imarker, su2double val_surface_normalvelocity)
Set the normal velocity at the surface.
void MergeSurfaceConnectivity(CConfig *config, CGeometry *geometry, unsigned short Elem_Type)
Merge the connectivity for a single element type from all processors.
virtual su2double * GetVecSolDOFs(void)
A virtual member.
Use a time stepping strategy for unsteady computations.
su2double GetLaminarViscosity()
Get fluid dynamic viscosity.
Definition: fluid_model.inl:49
virtual su2double GetCSensitivity(unsigned short val_marker, unsigned long val_vertex)
A virtual member.
su2double GetdCMz_dCL(void)
Value of the weight of the CD, CL, CM optimization.
VTK nomenclature for defining a pyramid element.
bool GetFSI_Simulation(void)
Check if the simulation we are running is a FSI simulation.
No slip constant heat flux wall boundary condition.
virtual su2double GetTotal_CSF(void)
A virtual member.
Definition of the continuous adjoint Euler&#39;s solver.
short GetRotation_Type(void)
Get the type of rotation associated to the vertex.
su2double GetCp()
Get fluid specific heat at constant pressure.
Definition: fluid_model.inl:38
virtual su2double GetTotal_CT(void)
A virtual member.
unsigned short GetnVar(void)
Get the number of variables of the problem.
Kind of transition model (Langtry-Menter (LM) for SST and Spalart-Allmaras).
Use a harmonic balance source term.
Main class for defining the Thermo-Physical Model a child class for each particular Model (Ideal-Gas...
Definition: fluid_model.hpp:54
Boolean definition of no.
bool GetFrozen_Visc_Disc(void)
Provides information about the way in which the turbulence will be treated by the disc...
unsigned short GetMarker_All_Analyze(unsigned short val_marker)
Get the plotting information for a marker val_marker.
su2double GetSurface_SecondOverUniform(unsigned short val_imarker)
Get the relative secondary flow strength at the surface.
su2double GetInc_Density_Ref(void)
Get the value of the reference density for custom incompressible non-dimensionalization.
virtual su2double GetTotal_CEquivArea(void)
A virtual member.
unsigned short GetnTimeInstances(void)
Retrieves the number of periodic time instances for Harmonic Balance.
string GetMarker_Analyze_TagBound(unsigned short val_marker)
Get the name of the surface defined in the geometry file.
virtual su2double GetSolution_Accel(unsigned long iPoint, unsigned long iVar) const
Get the acceleration (Structural Analysis).
Definition: CVariable.hpp:2324
virtual su2double GetAllBound_CMy_Visc(void)
A virtual member.
virtual su2double GetSurface_CMz_Mnt(unsigned short val_marker)
A virtual member.
virtual su2double GetTotal_Sens_Geo(void)
A virtual member.
unsigned short GetKind_HybridRANSLES(void)
Get the Kind of Hybrid RANS/LES.
Derivative with respect to the freestream density.
const unsigned short * GetSubConnType1(void) const
Function, which makes available the the connectivity of the linear elements of type 1 as a const poin...
void SortConnectivity_FEM(CConfig *config, CGeometry *geometry, unsigned short val_iZone)
Sort the connectivities (volume and surface) into data structures used for output file writing (DG-FE...
su2double GetSurface_Density(unsigned short val_imarker)
Get the density at an outlet boundary.
su2double GetRefArea(void)
Get the reference area for non dimensional coefficient computation. If the value from the is 0 then...
bool GetExtraOutput(void)
Creates a tecplot file to visualize the partition made by the DDC software.
virtual su2double GetAllBound_CMx_Inv(void)
A virtual member.
void SpecialOutput_HarmonicBalance(CSolver *****solver, CGeometry ****geometry, CConfig **config, unsigned short iZone, unsigned short val_nZone, bool output)
Write the output file for harmonic balance for each time-instance.
virtual su2double GetDensity_Inf(void)
A virtual member.
void SetSurface_Enthalpy(unsigned short val_imarker, su2double val_surface_enthalpy)
Set the enthalpy at the surface.
su2double GetNacelleLocation(unsigned short val_index)
Get the defintion of the nacelle location.
virtual su2double GetLaminarViscosity(unsigned long iPoint) const
A virtual member.
Definition: CVariable.hpp:1297
bool GetEngine_HalfModel(void)
Only halg of the engine is in the compputational grid.
su2double * GetRefOriginMoment(unsigned short val_marker)
Get reference origin for moment computation.
su2double GetSurface_IDC(unsigned short val_imarker)
Get the back pressure (static) at an outlet boundary.
short Short(const su2double &data)
Casts the primitive value to short (uses GetValue, already implemented for each type).
static void Bcast(void *buf, int count, Datatype datatype, int root, Comm comm)
Kind of Turbulent model (Spalart-Allmaras).
string GetUnsteady_FileName(string val_filename, int val_iter, string ext)
Augment the input filename with the iteration number for an unsteady file.
unsigned long GetOuterIter(void)
Get the current FSI iteration number.
virtual su2double GetSurface_CFy(unsigned short val_marker)
A virtual member.
unsigned short GetnObj(void)
Get the total number of objectives in kind_objective list.
virtual su2double GetStrainMag_Max(void)
A virtual member.
su2double GetMax_Delta_Time(void)
Get the value of the maximum delta time.
virtual su2double GetSurface_CMz_Visc(unsigned short val_marker)
A virtual member.
void SetBaselineResult_Files(CSolver ***solver, CGeometry ***geometry, CConfig **config, unsigned long iExtIter, unsigned short val_nZone)
Writes and organizes the all the output files, except the history one, for serial computations...
Constant Prandtl number.
su2double GetSurface_MassFlow(unsigned short val_imarker)
Get the massflow at an outlet boundary.
Non-dimensional incompressible simulation based on intial values for external flow.
unsigned short GetnMarker_ActDiskOutlet(void)
Get the total number of boundary markers.
void SetSurface_SecondaryStrength(unsigned short val_imarker, su2double val_surface_secondarystrength)
Set the secondary flow strength at the surface.
Main class for defining the PDE solution, it requires a child class for each particular solver (Euler...
Definition of the Euler&#39;s solver.
virtual su2double GetLoad_Increment(void)
A virtual member.
unsigned short GetSystemMeasurements(void)
Governing equations of the flow (it can be different from the run time equation). ...
const unsigned short N_POINTS_QUADRILATERAL
General output & CGNS defines.
void DeallocateSurfaceData_Parallel(CConfig *config, CGeometry *geometry)
Deallocate temporary memory needed for merging and writing output data in parallel.
su2double GetPressure_Ref(void)
Get the value of the reference pressure for non-dimensionalization.
Use a dual time stepping strategy for unsteady computations (1st order).
short GetMarker_All_SendRecv(unsigned short val_marker)
Get the send-receive information for a marker val_marker.
su2double GetReynolds(void)
Get the Reynolds number. Dimensionless number that gives a measure of the ratio of inertial forces to...
const int MASTER_NODE
Master node for MPI parallelization.
unsigned short GetKind_Average(void)
Get the kind of marker analyze marker (area-averaged, mass flux averaged, etc).
virtual su2double GetAllBound_CMx_Mnt(void)
A virtual member.
su2double GetFixAzimuthalLine(void)
Value of the azimuthal line to fix due to a misalignments of the nearfield.
su2double GetAoA(void)
Get the angle of attack of the body. This is the angle between a reference line on a lifting body (of...
virtual su2double GetTotal_CMx(void)
A virtual member.
unsigned long GetnPointDomain(void)
Get number of real points (that belong to the domain).
su2double GetSoundSpeed()
Get fluid speed of sound.
Definition: fluid_model.inl:32
virtual su2double GetSurface_CD_Inv(unsigned short val_marker)
A virtual member.
VTK nomenclature for defining a triangle element.
void SetSurface_DC60(unsigned short val_imarker, su2double val_surface_distortion)
Get the back pressure (static) at an outlet boundary.
void SetSurface_SecondOverUniform(unsigned short val_imarker, su2double val_surface_secondaryoverstream)
Set the relative secondary flow strength at the surface.
Derivative with respect to the mach number.
virtual void SetHeatFluxTarget(unsigned short val_marker, unsigned long val_vertex, su2double val_heat)
A virtual member.
virtual su2double GetAllBound_CMx_Visc(void)
A virtual member.
virtual su2double GetAllBound_CL_Mnt(void)
A virtual member.
string GetMultizone_HistoryFileName(string val_filename, int val_iZone, string ext)
Append the zone index to the restart or the solution files.
string GetSurfAdjCoeff_FileName(void)
Get the name of the file with the surface information for the adjoint problem.
virtual su2double GetHeatFluxTarget(unsigned short val_marker, unsigned long val_vertex)
A virtual member.
void LoadLocalData_IncFlow(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone)
Load the desired solution data into a structure used for parallel reordering and output file writing ...
virtual su2double GetRelaxCoeff()
A virtual member.
virtual void SetTotal_IDC_Mach(su2double val_Total_IDC_Mach)
A virtual member.
virtual su2double GetSurface_CEff_Visc(unsigned short val_marker)
A virtual member.
virtual su2double GetSurface_CD_Visc(unsigned short val_marker)
A virtual member.
const int TRANS_SOL
Position of the transition model solution in the solver container array.
Wing analysis.
void PrepareOffsets(CConfig *config, CGeometry *geometry)
Prepare the number of points and offsets for linear partitioning that are needed for output...
unsigned short GetRef_NonDim(void)
Get the kind of non-dimensionalization.
su2double * GetLimiter(unsigned long iPoint)
Get the value of the slope limiter.
Definition: CVariable.hpp:846
virtual unsigned long GetnElemHexa()
A virtual member.
virtual su2double GetSurface_CEff(unsigned short val_marker)
A virtual member.
Class to store a boundary for the FEM solver.
Polynomial thermal conductivity.
su2double GetNuFactor_FreeStream(void)
Get the value of the non-dimensionalized freestream turbulence intensity.
static void Allreduce(void *sendbuf, void *recvbuf, int count, Datatype datatype, Op op, Comm comm)
virtual su2double GetSurface_CFz_Inv(unsigned short val_marker)
A virtual member.
bool GetVisualize_Volume_Def(void)
Creates a tecplot file to visualize the volume deformation deformation made by the DEF software...
unsigned long GetnVertex(unsigned short val_marker)
Get number of vertices.
const su2double EPS
Error scale.
virtual su2double GetVelocity2(unsigned long iPoint) const
A virtual member.
Definition: CVariable.hpp:1283
Definition of the discrete adjoint FEM solver.
const unsigned short N_POINTS_PRISM
General output & CGNS defines.
unsigned short GetComm_Level(void)
Get the level of MPI communications to be performed.
void SortSurfaceConnectivity(CConfig *config, CGeometry *geometry, unsigned short Elem_Type)
Sort the connectivity for a single surface element type into a linear partitioning across all process...
virtual su2double GetRes_FEM(unsigned short val_var)
Get the residual for FEM structural analysis.
void SetRestart(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone)
Write a native SU2 restart file.
virtual su2double GetTotal_IDR(void)
A virtual member.
virtual su2double GetTotal_ComboObj(void)
Provide the total "combo" objective (weighted sum of other values).
su2double GetTurbulenceIntensity_FreeStream(void)
Get the value of the non-dimensionalized freestream turbulence intensity.
Derivative with respect to the sideslip angle.
#define MPI_SUM
su2double GetEA_ScaleFactor(void)
Get the integration limits for the equivalent area computation.
unsigned short GetnSpanMaxAllZones(void)
number span-wise sections to compute performance for turbomachinery.
Area-weighted average.
unsigned short GetGeo_Description(void)
Get Description of the geometry to be analyzed.
virtual su2double GetSurface_CMz(unsigned short val_marker)
A virtual member.
VTK nomenclature for defining a prism element.
Norm of displacements with respect to target geometry.
Constant viscosity.
void ComputeAirfoil_Section(su2double *Plane_P0, su2double *Plane_Normal, su2double MinXCoord, su2double MaxXCoord, su2double MinYCoord, su2double MaxYCoord, su2double MinZCoord, su2double MaxZCoord, su2double *FlowVariable, vector< su2double > &Xcoord_Airfoil, vector< su2double > &Ycoord_Airfoil, vector< su2double > &Zcoord_Airfoil, vector< su2double > &Variable_Airfoil, bool original_surface, CConfig *config)
A virtual member.
void SortConnectivity(CConfig *config, CGeometry *geometry, unsigned short val_iZone)
Sort the connectivities (volume and surface) into data structures used for output file writing...
bool GetWrt_MeshQuality(void)
Get information about writing the mesh quality metrics to the visualization files.
unsigned short GetnSpan_iZones(unsigned short iZone)
set number span-wise sections to compute 3D BC and performance for turbomachinery.
CSysVector< su2double > OutputVariables
vector to store the extra variables to be written.
virtual su2double GetSurface_CFz(unsigned short val_marker)
A virtual member.
virtual su2double GetPressure(unsigned long iPoint) const
A virtual member.
Definition: CVariable.hpp:1210
su2double GetEnergy_Ref(void)
Get the value of the reference pressure for non-dimensionalization.
virtual su2double GetSpecificHeatCv(unsigned long iPoint) const
A virtual member.
Definition: CVariable.hpp:1333
virtual su2double GetTotal_CoPy(void)
A virtual member.
su2double GetWall_Distance(void)
Get the value of the distance to the nearest wall.
Definition of incompressible solver.
virtual su2double GetGradient_Primitive(unsigned long iPoint, unsigned long iVar, unsigned long iDim) const
A virtual member.
Definition: CVariable.hpp:1927
virtual su2double GetAllBound_CSF_Inv(void)
A virtual member.
static void Isend(void *buf, int count, Datatype datatype, int dest, int tag, Comm comm, Request *request)
bool GetViscous(void)
Determines if problem is viscous.
virtual su2double GetFSI_Residual()
A virtual member.
Running the SU2_DOT software.
unsigned short GetRef_Inc_NonDim(void)
Get the kind of incompressible non-dimensionalization.
void MergeCoordinates_FEM(CConfig *config, CGeometry *geometry)
Merge the node coordinates from all processors for the FEM solver.
#define MPI_INT
string * OutputHeadingNames
vector of strings to store the headings for the exra variables
virtual su2double GetTotal_CoPz(void)
A virtual member.
double GetDerivative(const su2double &data)
Get the derivative value of the datatype (needs to be implemented for each new type).
su2double GetSurface_IDR(unsigned short val_imarker)
Get the back pressure (static) at an outlet boundary.
virtual su2double GetAllBound_CFx_Inv(void)
A virtual member.
bool GetWrt_Residuals(void)
Get information about writing residuals to volume solution file.
unsigned short GetnOutputVariables(void)
Get the number of variables of the problem.
CPrimalGrid *** bound
Boundary vector (primal grid information).
void SetSurface_Temperature(unsigned short val_imarker, su2double val_surface_temperature)
Set the temperature at the surface.
unsigned short GetVTK_Type(void) const
Function, which makes available the type of the element.
unsigned short GetVTK_Type2(void) const
Function, which makes available the type of the element in subConn2ForPlotting.
Kind of transition model (BAS-CAKMAKCIOGLU (BC) for Spalart-Allmaras).
Paraview binary format for the solution output.
vector< su2double > Orthogonality
Measure of dual CV orthogonality angle (0 to 90 deg., 90 being best).
string GetMultiInstance_HistoryFileName(string val_filename, int val_iInst)
Append the instance index to the restart or the solution files.
unsigned long GetNode(void)
Get the node of the vertex.
#define CURRENT_FUNCTION
virtual su2double GetAllBound_CFz_Visc(void)
A virtual member.
static void Waitall(int nrequests, Request *request, Status *status)
static void Barrier(Comm comm)
virtual su2double GetTotal_CFx(void)
A virtual member.
su2double GetRefLength(void)
Get the reference length for computing moment (the default value is 1).
void MergeConnectivity_FEM(CConfig *config, CGeometry *geometry, unsigned short val_iZone)
Merge the FEM geometry into a data structure used for output file writing.
virtual su2double GetSurface_CL_Visc(unsigned short val_marker)
A virtual member.
Definition of the discrete adjoint Navier-Stokes&#39; solver.
void MergeVolumetricConnectivity(CConfig *config, CGeometry *geometry, unsigned short Elem_Type)
Merge the connectivity for a single element type from all processors.
Definition of the discrete adjoint incompressible Euler solver.